CodeForces - 710F:String Set Queries (二进制分组 处理 在线AC自动机)
ou should process m queries over a set D of strings. Each query is one of three kinds:
- Add a string s to the set D. It is guaranteed that the string s was not added before.
- Delete a string s from the set D. It is guaranteed that the string s is in the set D.
- For the given string s find the number of occurrences of the strings from the set D. If some string p from D has several occurrences in s you should count all of them.
Note that you should solve the problem in online mode. It means that you can't read the whole input at once. You can read each query only after writing the answer for the last query of the third type. Use functions fflush in C++ and BufferedWriter.flush in Java languages after each writing in your program.
The first line contains integer m (1 ≤ m ≤ 3·105) — the number of queries.
Each of the next m lines contains integer t (1 ≤ t ≤ 3) and nonempty string s — the kind of the query and the string to process. All strings consist of only lowercase English letters.
The sum of lengths of all strings in the input will not exceed 3·105.
Output
For each query of the third kind print the only integer c — the desired number of occurrences in the string s.
Examples
5
1 abc
3 abcabc
2 abc
1 aba
3 abababc
2
2
10
1 abc
1 bcd
1 abcd
3 abcd
2 abcd
3 abcd
2 bcd
3 abcd
2 abc
3 abcd
3
2
1
0
题意:三种操作,1,给集合S加串;2,删串;3,询问子串在S出现的个数。 强制在线。
思路:如果不是强制在线,我们可以先对所有要加的串,建立AC自动机,然后用AC自动机+DFS序+线段树离线操作。
这里要求在线,主要问题就是如何高效的维护AC自动机的fail,我们用二进制来分块;使得每个串最多合并log次。。。
二进制分组:每次加串,就在尾巴建立一个字典树,集合大小为1; 如果集合大小和前面的相同,就合并到前面。 合并完后,对其建立AC自动机,得到fail和sum。
对于强制在线的题,这是个不错的方式,复杂度O(NlogN),不过常数有点大。 我们也可以用分块的思想去做,O(NsqrtN)。
(至于为什么网上都是加和删分别构造AC自动机,不太明白,感觉没必要。
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
char c[maxn]; int len;
struct ACAM{
int cnt,ch[maxn][],fail[maxn],ac[maxn][];
int rt[maxn],num[maxn],sum[maxn],tot[maxn],T;
ACAM(){
cnt=; T=;
rep(i,,) rt[i]=num[i]=;
}
queue<int>que;
void add(int &Now,int L,int opt)
{
if(!Now) Now=++cnt;
if(L==len+){ tot[Now]+=opt; return ;}
add(ch[Now][c[L]-'a'],L+,opt);
}
void build(int d) {
que.push(d); fail[d]=d; sum[d]=;
for (int i=;i<;i++) ac[d][i]=d;
while(!que.empty()) {
int u=que.front();que.pop();
sum[u]=sum[fail[u]]+tot[u];
for (int i=;i<;i++) if (ch[u][i]) {
int v=ch[u][i];
que.push(v); fail[v]=ac[fail[u]][i]; ac[u][i]=v;
} else ac[u][i]=ac[fail[u]][i];
}
}
int merge(int x,int y)
{
if(!x||!y) return x^y;
tot[x]+=tot[y];
rep(i,,)
ch[x][i]=merge(ch[x][i],ch[y][i]);
return x;
}
void insert(int opt)
{
T++; add(rt[T],,opt); num[T]=;
while(num[T]==num[T-]){
rt[T-]=merge(rt[T-],rt[T]);
rt[T]=; num[T-]+=num[T];
num[T]=; T--;
}
build(rt[T]);
}
ll query()
{
ll res=;
rep(i,,T) {
if(!rt[i]) continue;
int Now=rt[i];
rep(j,,len){
Now=ac[Now][c[j]-'a'];
res+=sum[Now];
}
}
return res;
}
}a;
int main()
{
int N,opt;
scanf("%d",&N);
rep(i,,N){
scanf("%d%s",&opt,c+);
len=strlen(c+);
if(opt==) a.insert();
else if(opt==) a.insert(-);
else printf("%lld\n",a.query()),fflush(stdout);
}
return ;
}
两个,分别表示加和删:
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
char c[maxn]; int len;
struct ACAM{
int cnt,ch[maxn][],fail[maxn],ac[maxn][];
int rt[maxn],num[maxn],sum[maxn],tot[maxn],T;
ACAM(){
cnt=; T=;
rep(i,,) rt[i]=num[i]=;
}
queue<int>que;
void add(int &Now,int L)
{
if(!Now) Now=++cnt;
if(L==len+){ tot[Now]++; return ;}
add(ch[Now][c[L]-'a'],L+);
}
void build(int d) {
que.push(d); fail[d]=d; sum[d]=;
for (int i=;i<;i++) ac[d][i]=d;
while(!que.empty()) {
int u=que.front();que.pop();
sum[u]=sum[fail[u]]+tot[u];
for (int i=;i<;i++) if (ch[u][i]) {
int v=ch[u][i];
que.push(v); fail[v]=ac[fail[u]][i]; ac[u][i]=v;
} else ac[u][i]=ac[fail[u]][i];
}
}
int merge(int x,int y)
{
if(!x||!y) return x^y;
tot[x]+=tot[y];
rep(i,,)
ch[x][i]=merge(ch[x][i],ch[y][i]);
return x;
}
void insert()
{
T++; add(rt[T],); num[T]=;
while(num[T]==num[T-]){
rt[T-]=merge(rt[T-],rt[T]);
rt[T]=; num[T-]+=num[T];
num[T]=; T--;
}
build(rt[T]);
}
ll query()
{
ll res=;
rep(i,,T) {
if(!rt[i]) continue;
int Now=rt[i];
rep(j,,len){
Now=ac[Now][c[j]-'a'];
res+=sum[Now];
}
}
return res;
}
}a,b;
int main()
{
int N,opt;
scanf("%d",&N);
rep(i,,N){
scanf("%d%s",&opt,c+);
len=strlen(c+);
if(opt==) a.insert();
else if(opt==) b.insert();
else printf("%lld\n",a.query()-b.query()),fflush(stdout);
}
return ;
}
CodeForces - 710F:String Set Queries (二进制分组 处理 在线AC自动机)的更多相关文章
- Codeforces 710F - String Set Queries(AC 自动机)
题面传送门 题意:强制在线的 AC 自动机. \(n,\sum|s|\leq 3\times 10^5\) 如果不是强制在线那此题就是道 sb 题,加了强制在线就不那么 sb 了. 这里介绍两种做法: ...
- Codeforces 710F String Set Quries
题意 维护一个字符串的集合\(D\), 支持3种操作: 插入一个字符串\(s\) 删除一个字符串\(s\) 查询一个字符串\(s\)在\(D\)中作为子串出现的次数 强制在线 解法 AC自动机+二进制 ...
- CodeForces 710F 强制在线AC自动机
题目链接:http://codeforces.com/contest/710/problem/F 题意:维护一个集合,集合要求满足三种操作. 1 str:向集合插入字符串str(保证不会插入之前已经插 ...
- 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组
F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...
- 【CF710F】String Set Queries(二进制分组,AC自动机)
[CF710F]String Set Queries(二进制分组,AC自动机) 题面 洛谷 CF 翻译: 你有一个字符集合\(D\),初始为空, 有三种操作: 往\(D\)中加入一个串:从\(D\)中 ...
- 【CF 710F】String Set Queries
在校内OJ上A了,没有加强制在线的东西..不放链接了. 这道题题意是维护一个字符串集合,支持三种操作: 1.加字符串 2.删字符串 3.查询集合中的所有字符串在给出的模板串中出现的次数 操作数\(m ...
- CF710F String Set Queries
CF710F String Set Queries 支持字符串的插入和删除...SAM也干不了这个事 所以可以用cdq分治+AC自动机O(nlogn)解决 但是本题强制在线~~~ 我们还有一个工具,叫 ...
- HDU 6166 Senior Pan(多校第九场 二进制分组最短路)
题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离 思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点 ...
- codeforces 1217E E. Sum Queries? (线段树
codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...
随机推荐
- python3使用requests模块完成get/post/代理/自定义header/自定义Cookie
一.背景说明 http请求的难易对一门语言来说是很重要的而且是越来越重要,但对于python一是urllib一些写法不太符合人的思维习惯文档也相当难看,二是在python2.x和python3.x中写 ...
- coursera国际法笔记 持续更新
LECTURE ONE International crime court(ICC) came into being after the Second World War. The Nuremberg ...
- nyoj 1091 还是01背包(超大数dp)
nyoj 1091 还是01背包 描述 有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值 1 <= n <=40 1 ...
- Win10系列:UWP界面布局进阶6
在Windows 10的"个性化设置"中,用户可以更改计算机在锁屏状态下的背景图片,除此之外,也可以通过Windows应用商店应用程序将喜欢的图片设置为锁屏背景,下面通过一个示例来 ...
- 在项目中使用 SCSS
背景概述 1. CSS预处理器 css预处理器定义了一种新的编程语言,编译后成正常的CSS文件.为CSS增加一些编程的特性,无需考虑浏览器的兼容问题,让CSS更加简洁,适应性更强,可读性更佳,更易于代 ...
- [转载]Java创建WebService服务及客户端实现
Java创建WebService服务及客户端实现 Java创建WebService服务及客户端实现
- day042 前端CSS选择器
今日内容: 高级选择器 1.子类选择器 用 > 表示 类比于相对路径 选择的是前一级标签的子标签 2后代选择器 用空格表示 选择的是前一级标签的后代标签 3并集选择器 用,逗号表示 选择的是用逗 ...
- 源码学习:一个express().get方法的加载与调用
刚刚接触express,它的中间件确实把我搞得头晕.get的回调中要不要加next?不加载还会执行下一个中间件么?给get指定'/'路径是不是所有以'/'开头的访问在没有确切匹配时都能执行?use件又 ...
- hibernate查询oracle数据库表报错SQL state [null]; error code [17027]; 流已被关闭; nested exception is java.sql.SQLException: 流已被关闭
把表字段类型 long 修改为 number类型即可
- DevExpress ASP.NET v18.2新功能详解(一)
行业领先的.NET界面控件2018年第二次重大更新——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍新版本新功能.本文将介绍了DevExpress ASP.NET Cont ...