【洛谷P3796】【模板】AC自动机(加强版)

来源:互联网 发布:网络健康度检测插件 编辑:程序博客网 时间:2024/06/16 12:58

题目描述

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

输入输出格式

输入格式:
输入含多组数据。

每组数据的第一行为一个正整数,表示共有个模式串,。

接下去行,每行一个长度小于等于的模式串。下一行是一个长度小于等于的文本串。

输入结束标志为。

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

输入输出样例

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

题解
在简单版上稍加改动,记录每个单词结束的节点位置,记录出现次数即可

代码

#include<cstdio>#include<cstring>#include<iostream>using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}char s[151][71],m[1000001];int tot,n,a[1000001][26],danger[1000001],point[1000001],Hash[1000001],ans[151];int q[1000001];inline void ins(int x){    int now=1,l=strlen(s[x]);    for (int i=0;i<l;i++)    {        int t=s[x][i]-'a';        if (!a[now][t]) a[now][t]=++tot;        now=a[now][t];    }    Hash[now]=x;}inline void acmach(){    int Head=0,tail=1;    q[1]=1;point[1]=0;    while (Head!=tail)    {        int now=q[++Head];        for (int i=0;i<26;i++)            if (a[now][i])            {                point[a[now][i]]=a[point[now]][i];                q[++tail]=a[now][i];            }            else a[now][i]=a[point[now]][i];    }}inline void solve(){    int now=1,l=strlen(m);    for (int i=0;i<l;i++)    {        int t=m[i]-'a';        now=a[now][t];        for (int j=now;j;j=point[j])            if (Hash[j]) ans[Hash[j]]++;    }}int main(){    n=read();    for (int i=0;i<26;i++) a[0][i]=1;    while (n)    {        tot=1;        for (int i=1;i<=n;i++)        {            scanf("%s",s[i]);            ins(i);        }        acmach();        scanf("%s",m);        solve();        int mx=0;        for (int i=1;i<=n;i++)            mx=max(mx,ans[i]);        printf("%d\n",mx);        for (int i=1;i<=n;i++)        {            if (mx==ans[i]) puts(s[i]);            ans[i]=0;        }        for (int i=1;i<=tot;i++)        {            Hash[i]=point[i]=danger[i]=0;            for (int j=0;j<26;j++)                a[i][j]=0;        }        n=read();    }    return 0;}