【模板】AC自动机

来自洛谷的两道AC自动机模板题;

【模板】AC自动机(简单版)

题目背景

这是一道简单的AC自动机模板题。

用于检测正确性以及算法常数。

为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。

管理员提示:本题数据内有重复的单词,且重复单词应该计算多次,请各位注意

题目描述

给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

输入输出格式

输入格式:

第一行一个n,表示模式串个数;

下面n行每行一个模式串;

下面一行一个文本串。

输出格式:

一个数表示答案

输入输出样例

输入样例#1:
2
a
aa
aa
输出样例#1:
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 1501N150。

接下去NNN行,每行一个长度小于等于707070的模式串。下一行是一个长度小于等于10610^6106​​的文本串TTT。

输入结束标志为N=0N=0N=0。

输出格式:

对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。

输入输出样例

输入样例#1:
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
输出样例#1:
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 }

 

那个,
2
a
ba
bababa
0
这个自己造的数据过不了、
posted @ 2017-08-08 17:26  J_william  阅读(263)  评论(0编辑  收藏  举报