模板AC自动机
Posted 鄉勇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板AC自动机相关的知识,希望对你有一定的参考价值。
来自洛谷的两道AC自动机模板题;
【模板】AC自动机(简单版)
题目背景
这是一道简单的AC自动机模板题。
用于检测正确性以及算法常数。
为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。
管理员提示:本题数据内有重复的单词,且重复单词应该计算多次,请各位注意
题目描述
给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。
输入输出格式
输入格式:第一行一个n,表示模式串个数;
下面n行每行一个模式串;
下面一行一个文本串。
输出格式:一个数表示答案
输入输出样例
2 a aa aa
2
说明
subtask1[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6,n=1;
subtask2[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6;
代码实现
1 #include<cstdio> 2 const int size=1e6+10; 3 int n,a,ans; 4 int q[size],h,t; 5 char ch[size],cn[size]; 6 int next[size][26],fail[size],v[size],sz; 7 int main(){ 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++){ 10 scanf("%s",ch); 11 for(int j=0,k=0;;j++,k=next[k][a]){ 12 if(!ch[j]){ 13 v[k]++; 14 break; 15 } 16 a=ch[j]-‘a‘; 17 if(!next[k][a])next[k][a]=++sz; 18 } 19 } 20 q[t++]=0; 21 while(h<t){ 22 a=q[h++]; 23 for(int i=0,j;i<26;i++) 24 if(next[a][i]){ 25 j=fail[a]; 26 while(j&&next[j][i]==0) j=fail[j]; 27 fail[next[a][i]]=j!=a?next[j][i]:0; 28 q[t++]=next[a][i]; 29 } 30 } 31 scanf("%s",cn); 32 for(int i=0,k=0;cn[i];i++){ 33 a=cn[i]-‘a‘; 34 while(k&&next[k][a]==0) k=fail[k]; 35 k=next[k][a]; 36 if(v[k]!=-1){ 37 for(int j=k;j&&v[j]!=-1;j=fail[j]) 38 ans+=v[j],v[j]=-1; 39 } 40 } 41 printf("%d\n",ans); 42 return 0; 43 }
【模板】AC自动机(加强版)
题目描述
有NNN个由小写字母组成的模式串以及一个文本串TTT。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串TTT中出现的次数最多。
输入输出格式
输入格式:输入含多组数据。
每组数据的第一行为一个正整数NNN,表示共有NNN个模式串,1≤N≤1501 \leq N \leq 1501≤N≤150。
接下去NNN行,每行一个长度小于等于707070的模式串。下一行是一个长度小于等于10610^610?6??的文本串TTT。
输入结束标志为N=0N=0N=0。
输出格式:对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。
输入输出样例
2 aba bab ababababac 6 beta alpha haha delta dede tata dedeltalphahahahototatalpha 0
4 aba 2 alpha haha
1 #include<cstdio> 2 #include<cstring> 3 inline int max_(int x,int y){return x>y?x:y;} 4 const int maxn=1<<9-1; 5 const int maxl=1<<21-1; 6 const int size=1<<18-1; 7 int n,a; 8 int q[size],h,t; 9 int tot[maxn],ans; 10 char ch[maxn][maxn],cn[maxl]; 11 int next[size][26],fail[size],to[size],sz; 12 void find(int k){ 13 int i,j; 14 for(i=to[k],j=fail[k];j;j=fail[j]) i=to[j]?to[j]:i; 15 to[k]=i; 16 } 17 int main(){ 18 while(scanf("%d",&n),n){ 19 ans=sz=h=t=0; 20 memset(to,0,sizeof(to)); 21 memset(tot,0,sizeof(tot)); 22 memset(next,0,sizeof(next)); 23 memset(fail,0,sizeof(fail)); 24 for(int i=1;i<=n;i++){ 25 scanf("%s",ch[i]); 26 for(int j=0,k=0;;j++,k=next[k][a]){ 27 if(!ch[i][j]){to[k]=i;break;} 28 a=ch[i][j]-‘a‘; 29 if(!next[k][a]) next[k][a]=++sz; 30 } 31 } 32 q[t++]=0; 33 while(h<t){ 34 a=q[h++]; 35 for(int i=0,j;i<26;i++) 36 if(next[a][i]){ 37 j=fail[a]; 38 while(j&&next[j][i]==0) j=fail[j]; 39 fail[next[a][i]]=j!=a?next[j][i]:0; 40 q[t++]=next[a][i]; 41 } 42 } 43 h=0; 44 while(h<t) 45 find(q[h++]); 46 scanf("%s",cn); 47 for(int i=0,k=0;cn[i];i++){ 48 a=cn[i]-‘a‘; 49 while(k&&next[k][a]==0) k=fail[k]; 50 k=next[k][a]; 51 if(to[k]) ans=max_(ans,++tot[to[k]]); 52 } 53 printf("%d\n",ans); 54 for(int i=1;i<=n;i++) 55 if(tot[i]==ans) 56 puts(ch[i]); 57 } 58 return 0; 59 }
a
ba
bababa
0
以上是关于模板AC自动机的主要内容,如果未能解决你的问题,请参考以下文章
HDU3247 Resource Archiver(AC自动机+BFS+DP)
HDU-2222-Keywords Search(AC自动机模板)