AC自动机(加强版)

题目描述

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

输入输出格式

输入格式:

 

输入含多组数据。

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

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

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

 

输出格式:

 

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

 

输入输出样例

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


ac自动机,last指针版
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int  maxn = 100001;
int n;
char s[maxn][101];
char ss[maxn*10];
int ans=0;
struct Aho_Corasick_automato {
    int sz;
    int ch[maxn][26];
    int cnt[maxn];
    int val[maxn];
    int last[maxn];
    int fail[maxn];
    int num;
    void init() {
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
        sz=1;
    }
    void insert(char *s,int num) {
        int len=strlen(s);
        int u=0;
        for(int i=0; i<len; ++i) {
            int v=(s[i]-'a');
            if(!ch[u][v]) {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][v]=sz++;
            }
            u=ch[u][v];
        }
        val[u]=num;
    }
    void get_fail() {
        fail[0]=0;
        queue<int>que;
        for(int i=0; i<26; i++) {
            int u=ch[0][i];
            if(u) {
                fail[u]=0;
                que.push(u);
            }
        }
        while(!que.empty()) {
            int u=que.front();
            que.pop();
            for(int i=0; i<26; i++) {
                int v=ch[u][i];
                if(!v) {
                    ch[u][i]=ch[fail[u]][i];
                    continue;
                }
                que.push(v);
                int k=fail[u];
                fail[v]=ch[k][i];
                last[v]=val[fail[v]] ? fail[v] : last[fail[v]];
            }
        }
    }
    void work(int x) {
        if(x) {
            cnt[val[x]]++;
            work(last[x]);
        }
    }
    void find(char *s) {
        int len=strlen(s);
        int u=0;
        for(int i=0; i<len; i++) {
            int v=(s[i]-'a');
            if(!ch[u][v])u=fail[u];
            while(u&&!ch[u][v])
                u=fail[u];
            u=ch[u][v];
            if(val[u])
                work(u);
            else if(last[u])
                work(last[u]);
        }
    }
} ac;

int main() {


    while(scanf("%d",&n)==1&&n!=0) {
        ac.init();
        for(int i=1; i<=n; i++) {
            scanf("%s",s[i]);
            ac.insert(s[i],i);
        }
        ac.get_fail();
        scanf("%s",ss);
        ac.find(ss);
        int ans=0,r;
        for(int i=1;i<=n;i++)
            if(ac.cnt[i]>ans)ans=ac.cnt[i],r=i;;
        printf("%d\n",ans);
         for(int r=1;r<=n;r++)
            if(ac.cnt[r]==ans)
                printf("%s\n",s[r]);
        }
    return 0;
}

 



posted @ 2017-07-30 15:27  zzzzx  阅读(495)  评论(0编辑  收藏  举报