CF710F String Set Queries
Posted pthws
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF710F String Set Queries相关的知识,希望对你有一定的参考价值。
维护一个字符串集合,支持三种操作:
1.加字符串
2.删字符串
3.查询集合中的所有字符串在给出的模板串中出现的次数
操作数m≤3∗10^5,输入字符串总长度L≤4∗10^6
AC自动机+二进制分组
二进制分组的基本思想是把修改操作按二的次幂分组,遇到修改就在尾部加一个,且与之前的合并(暴力重构),比如之前有23(16+4+2+1)个,加了一个后就变成了24(16+8)个,遇到查询就在每个组内查询,再加起来就好了,所以修改对询问的贡献独立时才能用二进制分组。
这道题对于加的串和删的串分别维护,查询时相减即可。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<string> #include<iostream> #include<vector> using namespace std; const int N=300005; struct node int ch[26],fail,w; g; vector<node> vct[2][30]; int m,t,i,num[2],w[2][30],cnt[2],sz[2][30],q[N],bg,ed,head[N],adj[N],nxt[N]; string s,str[2][N]; bool v[N]; void dfs(int id,int cnt,int x,int w) w+=vct[id][cnt][x].w; vct[id][cnt][x].w=w; for(int y=head[x];y;y=nxt[y]) dfs(id,cnt,adj[y],w); void add(int id) int i,j,k,x,y,z,len; str[id][++num[id]]=s; for(i=cnt[id],j=1;i>=1;--i) if(!v[j+w[id][i]]) break; j+=w[id][i]; vct[id][i].clear(); cnt[id]=i+1; w[id][cnt[id]]=j; sz[id][cnt[id]]=1; vct[id][cnt[id]].clear(); vct[id][cnt[id]].push_back(g); for(k=num[id]-j+1;k<=num[id];++k) len=str[id][k].size(); for(x=y=0;x<len;++x) z=str[id][k][x]-‘a‘; if(!vct[id][cnt[id]][y].ch[z]) vct[id][cnt[id]][y].ch[z]=sz[id][cnt[id]]++; vct[id][cnt[id]].push_back(g); y=vct[id][cnt[id]][y].ch[z]; vct[id][cnt[id]][y].w++; bg=1,ed=0; for(i=0;i<26;++i) if(vct[id][cnt[id]][0].ch[i]) q[++ed]=vct[id][cnt[id]][0].ch[i]; while(bg<=ed) for(i=0;i<26;++i) if(vct[id][cnt[id]][q[bg]].ch[i]) q[++ed]=vct[id][cnt[id]][q[bg]].ch[i]; vct[id][cnt[id]][q[ed]].fail=vct[id][cnt[id]][vct[id][cnt[id]][q[bg]].fail].ch[i]; else vct[id][cnt[id]][q[bg]].ch[i]=vct[id][cnt[id]][vct[id][cnt[id]][q[bg]].fail].ch[i]; ++bg; for(i=sz[id][cnt[id]]-1;i>=0;--i) head[i]=0; for(i=sz[id][cnt[id]]-1;i>0;--i) adj[i]=i; nxt[i]=head[vct[id][cnt[id]][i].fail]; head[vct[id][cnt[id]][i].fail]=i; dfs(id,cnt[id],0,0); long long work(int id) int i,j,k,len=s.size(); long long rtn=0; for(i=1;i<=cnt[id];++i) for(j=k=0;j<len;++j) k=vct[id][i][k].ch[s[j]-‘a‘]; rtn+=vct[id][i][k].w; return rtn; int main() cin>>m; for(i=0;(1<<i)<N;++i) v[1<<i]=true; while(m--) cin>>t>>s; if(t==1||t==2) add(t-1); else cout<<work(0)-work(1)<<endl; cout.flush(); return 0;
以上是关于CF710F String Set Queries的主要内容,如果未能解决你的问题,请参考以下文章