AC自动机
放三个板子
板子1:
#include<bits/stdc++.h> using namespace std; const int N=2e6; int tire[N][26],fail[N],n,tot=1,end[N],ans; char str[N]; inline void insert(char *a) { int n=strlen(a+1),p=1; for(int i=1;i<=n;++i) { int ch=a[i]-'a'; if(!tire[p][ch]) tire[p][ch]=++tot; p=tire[p][ch]; } end[p]++; } inline void get_fail() { queue<int>q;q.push(1); fail[1]=0; for(int i=0;i<26;++i) tire[0][i]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=0;i<26;++i) { if(!tire[x][i]) {tire[x][i]=tire[fail[x]][i];continue;} fail[tire[x][i]]=tire[fail[x]][i];q.push(tire[x][i]); } } } inline int AC(char *a) { int n=strlen(a+1),p=1; for(int i=1;i<=n;++i) { int ch=a[i]-'a'; int k=tire[p][ch]; while(k>1&&end[k]!=-1) { ans+=end[k];end[k]=-1; k=fail[k]; } p=tire[p][ch]; } return ans; } int main() { freopen("1.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s",str+1); insert(str); } get_fail(); scanf("%s",str+1); printf("%d",AC(str)); return 0; }
板子2:
#include<bits/stdc++.h> using namespace std; const int N=1e5,qwq=1e6+10; int n,tire[N][26],tot=1,end[N],cnt[N],fail[N]; char str[200][100]; char ch[qwq]; inline void insert(char *a,int s) { int n=strlen(a+1),p=1; for(int i=1;i<=n;++i) { int ch=a[i]-'a'; if(!tire[p][ch]) tire[p][ch]=++tot; p=tire[p][ch]; } end[p]=s; } inline void get_fail() { queue<int>q;q.push(1); fail[1]=0; for(int i=0;i<26;++i) tire[0][i]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=0;i<26;++i) { if(!tire[x][i]) {tire[x][i]=tire[fail[x]][i];continue;} fail[tire[x][i]]=tire[fail[x]][i];q.push(tire[x][i]); } } } inline void AC(char *a) { int m=strlen(a+1),p=1; for(int i=1;i<=m;++i) { int ch=a[i]-'a'; int k=tire[p][ch]; while(k>1) { cnt[end[k]]++; k=fail[k]; } p=tire[p][ch]; //cout<<i<<' '<<cnt[1]<<' '<<cnt[2]<<endl; } int mx=0; for(int i=1;i<=n;++i) mx=max(mx,cnt[i]); printf("%d\n",mx); for(int i=1;i<=n;++i) if(cnt[i]==mx) printf("%s\n",str[i]+1); } int main() { freopen("1.in","r",stdin); while(scanf("%d",&n)) { if(n==0) break; memset(tire,0,sizeof(tire)); memset(fail,0,sizeof(fail)); memset(end,0,sizeof(end)); memset(cnt,0,sizeof(cnt)); tot=1; for(int i=1;i<=n;++i) { scanf("%s",str[i]+1); insert(str[i],i); } get_fail(); scanf("%s",ch+1); AC(ch); } return 0; }
板子3(拓扑优化):
#include<bits/stdc++.h> using namespace std; const int N=2e6; int tire[N][26],fail[N],n,tot=1,end[N],ans; char str[N]; inline void insert(char *a) { int n=strlen(a+1),p=1; for(int i=1;i<=n;++i) { int ch=a[i]-'a'; if(!tire[p][ch]) tire[p][ch]=++tot; p=tire[p][ch]; } end[p]++; } inline void get_fail() { queue<int>q;q.push(1); fail[1]=0; for(int i=0;i<26;++i) tire[0][i]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=0;i<26;++i) { if(!tire[x][i]) {tire[x][i]=tire[fail[x]][i];continue;} fail[tire[x][i]]=tire[fail[x]][i];q.push(tire[x][i]); } } } inline int AC(char *a) { int n=strlen(a+1),p=1; for(int i=1;i<=n;++i) { int ch=a[i]-'a'; int k=tire[p][ch]; while(k>1&&end[k]!=-1) { ans+=end[k];end[k]=-1; k=fail[k]; } p=tire[p][ch]; } return ans; } int main() { freopen("1.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s",str+1); insert(str); } get_fail(); scanf("%s",str+1); printf("%d",AC(str)); return 0; }