您的位置:首页 > 其它

模板 AC自动机

2018-02-10 15:01 363 查看

题目描述

有$N$ 个由小写字母组成的模式串以及一个文本串$T$ 。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串$T$ 中出现的次数最多。

输入输出格式

输入格式:

输入含多组数据。

每组数据的第一行为一个正整数$N$ ,表示共有$N$ 个模式串,$1 \leq N \leq 150$ 。

接下去$N$ 行,每行一个长度小于等于$70$ 的模式串。下一行是一个长度小于等于$10^6$ 的文本串$T$ 。

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

输出格式:

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

输入输出样例

输入样例#1:
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0


输出样例#1:
4
aba
2
alpha
haha
传送门
AC自动机板子


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
char s[152][72],ss[1000001];
int n,ch[15001][27],size,val[15001],f[15001],ans,cnt[15001],ansnum;
queue<int>Q;
void insert(int len,int id)
{int i;
int now=0;
for (i=0;i<len;i++)
{
if (ch[now][s[id][i]-'a']==0)
ch[now][s[id][i]-'a']=++size;
now=ch[now][s[id][i]-'a'];
}
val[now]=id;
}
void AC_build()
{int i;
for (i=0;i<26;i++)
if (ch[0][i])
f[ch[0][i]]=0,Q.push(ch[0][i]);
while (Q.empty()==0)
{
int u=Q.front();
Q.pop();
for (i=0;i<26;i++)
{
if (ch[u][i]) f[ch[u][i]]=ch[f[u]][i],Q.push(ch[u][i]);
else ch[u][i]=ch[f[u]][i];
}
}
}
void query()
{int i,j;
int now=0;
int len=strlen(ss);
for (i=0;i<len;i++)
{
now=ch[now][ss[i]-'a'];
for (j=now;j&&val[j]!=-1;j=f[j])
cnt[val[j]]++;
}
}
int main()
{int i;
while (cin>>n&&n)
{
size=0;
memset(ch,0,sizeof(ch));
memset(cnt,0,sizeof(cnt));
memset(val,0,sizeof(val));
for (i=1;i<=n;i++)
{
scanf("%s",s[i]);
insert(strlen(s[i]),i);
}
AC_build();
scanf("%s",ss);
query();
ans=0;
for (i=1;i<=n;i++)
if (cnt[i]>ans)
{
ans=cnt[i];
}
printf("%d\n",ans);
for (i=1;i<=n;i++)
if (cnt[i]==ans)
{
printf("%s\n",s[i]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: