您的位置:首页 > 其它

【模板】AC自动机

2017-08-08 17:26 417 查看
来自洛谷的两道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;

代码实现

#include<cstdio>
const int size=1e6+10;
int n,a,ans;
int q[size],h,t;
char ch[size],cn[size];
int next[size][26],fail[size],v[size],sz;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",ch);
for(int j=0,k=0;;j++,k=next[k][a]){
if(!ch[j]){
v[k]++;
break;
}
a=ch[j]-'a';
if(!next[k][a])next[k][a]=++sz;
}
}
q[t++]=0;
while(h<t){
a=q[h++];
for(int i=0,j;i<26;i++)
if(next[a][i]){
j=fail[a];
while(j&&next[j][i]==0) j=fail[j];
fail[next[a][i]]=j!=a?next[j][i]:0;
q[t++]=next[a][i];
}
}
scanf("%s",cn);
for(int i=0,k=0;cn[i];i++){
a=cn[i]-'a';
while(k&&next[k][a]==0) k=fail[k];
k=next[k][a];
if(v[k]!=-1){
for(int j=k;j&&v[j]!=-1;j=fail[j])
ans+=v[j],v[j]=-1;
}
}
printf("%d\n",ans);
return 0;
}


【模板】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。

输出格式:

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

输入输出样例

输入样例#1:

2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0


输出样例#1:

4
aba
2
alpha
haha


代码实现

#include<cstdio>
#include<cstring>
inline int max_(int x,int y){return x>y?x:y;}
const int maxn=1<<9-1;
const int maxl=1<<21-1;
const int size=1<<18-1;
int n,a;
int q[size],h,t;
int tot[maxn],ans;
char ch[maxn][maxn],cn[maxl];
int next[size][26],fail[size],to[size],sz;
void find(int k){
int i,j;
for(i=to[k],j=fail[k];j;j=fail[j]) i=to[j]?to[j]:i;
to[k]=i;
}
int main(){
while(scanf("%d",&n),n){
ans=sz=h=t=0;
memset(to,0,sizeof(to));
memset(tot,0,sizeof(tot));
memset(next,0,sizeof(next));
memset(fail,0,sizeof(fail));
for(int i=1;i<=n;i++){
scanf("%s",ch[i]);
for(int j=0,k=0;;j++,k=next[k][a]){
if(!ch[i][j]){to[k]=i;break;}
a=ch[i][j]-'a';
if(!next[k][a]) next[k][a]=++sz;
}
}
q[t++]=0;
while(h<t){
a=q[h++];
for(int i=0,j;i<26;i++)
if(next[a][i]){
j=fail[a];
while(j&&next[j][i]==0) j=fail[j];
fail[next[a][i]]=j!=a?next[j][i]:0;
q[t++]=next[a][i];
}
}
h=0;
while(h<t)
find(q[h++]);
scanf("%s",cn);
for(int i=0,k=0;cn[i];i++){
a=cn[i]-'a';
while(k&&next[k][a]==0) k=fail[k];
k=next[k][a];
if(to[k]) ans=max_(ans,++tot[to[k]]);
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)
if(tot[i]==ans)
puts(ch[i]);
}
return 0;
}


那个,
2
a
ba
bababa
0
这个自己造的数据过不了、
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: