题面
https://www.luogu.org/problem/CF710F
题解
删除的情况另开一个“可支持插入的$AC$自动机”,因为贡献可减。
支持插入的$AC$自动机$=$$AC$自动机$+$二进制分组。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #define ri register int #define N 300300 #define pb push_back using namespace std; struct node { int son[26],fail,v; } t[N]; int st[N],top; int newnode() { return st[top--]; } void insert(int u,string s){ for (ri i=0,l=s.size();i<l;i++) { if (!t[u].son[s[i]-97]) t[u].son[s[i]-97]=newnode(); u=t[u].son[s[i]-97]; } t[u].v++; } void del(int rt){ if (!rt) return; for (ri i=0;i<26;i++) del(t[rt].son[i]),t[rt].son[i]=0; t[rt].fail=t[rt].v=0; st[++top]=rt; } struct group { vector<string> p; int tot,rt; void insert(string s) { p.pb(s); ++tot; } void clear() { del(rt); rt=newnode(); p.clear(); tot=0; } void build() { del(rt); rt=newnode(); for (ri i=0;i<tot;++i) Insert(rt,p[i]); queue<int> q; t[rt].fail=rt; for (ri i=0;i<26;i++) if (t[rt].son[i]) q.push(t[rt].son[i]),t[t[rt].son[i]].fail=rt; while (!q.empty()) { int u=q.front(); q.pop(); for (ri i=0;i<26;i++) if (t[u].son[i]) { int p=t[u].fail,v=t[u].son[i]; while (p!=rt && !t[p].son[i]) p=t[p].fail; if (t[p].son[i]) t[v].fail=t[p].son[i]; else t[v].fail=rt; q.push(v); t[v].v+=t[t[v].fail].v; } } } int query(string s) { int ret=0,u=rt; for (ri i=0,l=s.size();i<l;i++) { int c=s[i]-97; if (t[u].son[c]) u=t[u].son[c]; else { int p=t[u].fail; while (p!=rt && !t[p].son[c]) p=t[p].fail; if (t[p].son[c]) u=t[p].son[c]; else u=rt; } ret+=t[u].v; } return ret; } } A[20],B[20]; int tp1,tp2; void insert(string s){ ++tp1; A[tp1].clear(); A[tp1].insert(s); while (tp1>1 && A[tp1].tot==A[tp1-1].tot) { for (ri i=0;i<A[tp1].tot;i++) A[tp1-1].insert(A[tp1].p[i]); A[tp1--].clear(); } A[tp1].build(); } void delete(string s){ ++tp2; B[tp2].clear(); B[tp2].insert(s); while (tp2>1 && B[tp2].tot==B[tp2-1].tot) { for (ri i=0;i<B[tp2].tot;i++) B[tp2-1].insert(B[tp2].p[i]); B[tp2--].clear(); } B[tp2].build(); } int query(string s){ int ret=0; for (ri i=1;i<=tp1;i++) ret+=A[i].query(s); for (ri i=1;i<=tp2;i++) ret-=B[i].query(s); return ret; } string s; int main(){ ios::sync_with_stdio(false); for (ri i=1;i<N;i++) st[++top]=i; int m,opt; cin>>m; for (ri i=1;i<=m;i++) { cin>>opt>>s; if (opt==1) insert(s); if (opt==2) Delete(s); if (opt==3) cout<<query(s)<<endl; } }