#include<bits/stdc++.h>#define ll long long
using namespace std;constint maxn =6e5+10;int ch[maxn][26], f[maxn], val[maxn], sz, d[maxn];
queue<int> S;struct AC{
vector<string> G;int n, rt;voiddel(int o){for(int i =0; i <26; i++)if(ch[o][i])del(ch[o][i]);
f[o]= val[o]=0;for(int i =0; i <26; i++)
ch[o][i]=0;if(o != rt)
S.push(o);}voidinit(){del(rt);
G.clear();
n =0;}voidinsert(int o, string s){for(int i =0; s[i]; i++){int c = s[i]-'a';if(!ch[o][c])
ch[o][c]= S.front(), S.pop();
o = ch[o][c];}
val[o]++;}voidinsert(string s){
G.push_back(s);
n++;insert(rt, s);}voidbuild(){int o = rt;
queue<int> q;for(int i =0; i <26; i++)if(ch[o][i])
q.push(ch[o][i]), f[ch[o][i]]= rt, d[ch[o][i]]= val[ch[o][i]];while(!q.empty()){
o = q.front();
q.pop();for(int i =0; i <26; i++)if(ch[o][i]){int v = ch[o][i];
d[v]= val[v];int fa = f[o];while(fa != rt &&!ch[fa][i])
fa = f[fa];
f[v]= ch[fa][i];if(!f[v])
f[v]= rt;
d[v]+= d[f[v]];
q.push(v);}}}intfind(string s){int ans =0, o = rt;for(int i =0; s[i]; i++){int c = s[i]-'a';while(o != rt &&!ch[o][c])
o = f[o];
o = ch[o][c];if(!o)
o = rt;
ans += d[o];}return ans;}} A[2][21];int cat[2];
string s;voidup(int p){++cat[p];
A[p][cat[p]].insert(s);while(cat[p]>1&& A[p][cat[p]-1].n == A[p][cat[p]].n){for(int i =0; i < A[p][cat[p]].n; i++)
A[p][cat[p]-1].insert(A[p][cat[p]].G[i]);
A[p][cat[p]].init();--cat[p];}
A[p][cat[p]].build();}intquery(int p){int ans =0;for(int i =1; i <= cat[p]; i++)
ans += A[p][i].find(s);return ans;}intmain(){for(int i =0; i <=20; i++)
A[0][i].rt =++sz, A[1][i].rt =++sz;for(int i = sz +1; i < maxn; i++)
S.push(i);int m, opt;
cin>>m;while(m--){
cin>>opt>>s;if(opt ==1)up(0);elseif(opt ==2)up(1);elseprintf("%d\n",query(0)-query(1));}}
Educational Codeforces Round 16 F. String Set Queries AC自动机
F. String Set Queries题意:有三种操作:分别是往集合加入一个字符串,从集合中删除一个字符串,查询集合的所有串在询问串中出现次数的总和。解法:离线可以建AC自动机fail树上dfs序搞,强制在线可以采取二进制分组去建log个自动机A,二进制分组是个什么东西呢?举个例子:我往集合插入8次字符串,那么8次更新集合中所有自动机的大小分别是{1},{2},{2,1},{4},{4,...