UVALive-4670 Dominating Patterns / 洛谷 3796 【模板】AC自动机

https://vjudge.net/problem/UVALive-4670

中文题面:https://www.luogu.org/problem/show?pid=3796

 

AC自动机模板

注意如果有重复字符串,要输出所有的重复字符串

可以用重复字符串中标号最小的字符串来表示所有的重复字符串

例:

aba

abba

aba

aba出现了2次,

令mp[1]=mp[3]=1

代码实现的话,只需要在insert的最后判断,

如果这个单词节点还没有标记,标记上这个单词的编号

如果有标记,令当前单词的mp等于单词节点的标记

 

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

char s[1001001],ss[161][81];
int sum[151],bl[151*81];
int trie[151*81][27],tot;
int len,root,id;
int f[151*81];
int mp[151];
queue<int>q;

struct AhoCorasickAutomata
{
    void insert(int j)
    {
        len=strlen(ss[j]);
        root=1; 
        for(int i=0;i<len;i++)
        {
            id=ss[j][i]-'a';
            if(!trie[root][id]) 
            {
                trie[root][id]=++tot;
                bl[tot]=0;
                memset(trie[tot],0,sizeof(trie[tot]));
            }
            root=trie[root][id];
        }
        if(!bl[root]) bl[root]=j;
        mp[j]=bl[root];
    }
    void getfail()
    {
        memset(f,0,sizeof(f));
        for(int i=0;i<26;i++) trie[0][i]=1;
        q.push(1);
        int now,j;
        while(!q.empty())
        {
            now=q.front();q.pop();
            for(int i=0;i<26;i++)
            {
                if(!trie[now][i]) continue;
                q.push(trie[now][i]);
                j=f[now];
                while(!trie[j][i]) j=f[j];
                f[trie[now][i]]=trie[j][i];
            }
        }
    }
    void find()
    {
        len=strlen(s);
        memset(sum,0,sizeof(sum));
        root=1; int j;
        for(int i=0;i<len;i++)
        {
            id=s[i]-'a';
            while(!trie[root][id]) root=f[root];
            root=trie[root][id];
            j=root;
            while(j)
            {
                sum[bl[j]]++;
                j=f[j];
            }
        }
    }
};

AhoCorasickAutomata AC;

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(!n) return 0;
        tot=1;
        memset(trie[1],0,sizeof(trie[1]));
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ss[i]);
            AC.insert(i);
        }
        AC.getfail();
        scanf("%s",s);
        AC.find();
        int maxn=0;
        for(int i=1;i<=n;i++)    maxn=max(maxn,sum[i]);
        printf("%d\n",maxn);
        for(int i=1;i<=n;i++) 
           if(sum[mp[i]]==maxn) puts(ss[i]);
    }
}

 

posted @ 2017-06-10 15:41  TRTTG  阅读(398)  评论(0编辑  收藏  举报