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

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

题目描述

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

输入输出格式

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

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

接下去NN 行,每行一个长度小于等于7070 的模式串。下一行是一个长度小于等于10^610
6
的文本串TT 。

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

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

输入输出样例

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

分析:fail指针说一下,ac[ac[u].nxt[i]].fail=ac[ac[u].fail].nxt[i]。怕以后忘了。。。

代码

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <queue>
#define N 100000
using namespace std;
queue <int>q;

struct node
{
    int nxt[26],en,fail,sce;
}trie[N];
int n,ans,num,a[160];
string s[160];

void ins(string s1,int x)
{
    int len=s1.length();
    int u=0;
    for (int i=0;i<len;i++)
    {
        int v=s1[i]-'a';
        if (!trie[u].nxt[v]) trie[u].nxt[v]=++num;
        u=trie[u].nxt[v];
    }
    trie[u].en=1;
    trie[u].sce=x;
}

void getfail()
{
    while (!q.empty()) q.pop();
    for (int i=0;i<26;i++)
        if (trie[0].nxt[i])
        {
            trie[trie[0].nxt[i]].fail=0;
            q.push(trie[0].nxt[i]);
        }
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        for (int i=0;i<26;i++)
            if (trie[u].nxt[i])
            {
                trie[trie[u].nxt[i]].fail=trie[trie[u].fail].nxt[i];
                q.push(trie[u].nxt[i]);
            }
            else trie[u].nxt[i]=trie[trie[u].fail].nxt[i];
    }
}

void find(char *s1)
{
    int len=strlen(s1);
    int u=0;
    for (int i=0;i<len;i++)
    {
        int v=s1[i]-'a';
        u=trie[u].nxt[v];
        for (int j=u;j;j=trie[j].fail)
            if (trie[j].en) a[trie[j].sce]++;
    }
}

int main()
{
    scanf("%d",&n);
    while (n)
    {
        if (n==0) break;
        num=0;ans=0;
        memset(trie,0,sizeof(trie));
        memset(a,0,sizeof a);
        for (int i=1;i<=n;i++)
        {
            cin>>s[i];
            ins(s[i],i);
        }
        getfail();
        char t[1000005];
        scanf("%s",t);
        find(t);
        for (int i=1;i<=n;i++)
            ans=max(ans,a[i]);
        printf("%d\n",ans);
        for (int i=1;i<=n;i++)
            if (a[i]==ans) cout<<s[i]<<endl;
        scanf("%d",&n);
    }
}

猜你喜欢

转载自blog.csdn.net/zhanghaoxian1/article/details/79264907