AC自动机模板

大意:
给你一些模板串, 然后给你一些文本串, 对于每个文本串, 输出它中间出现次数最多的模板串和次数(可能有多个);

这当然是模板。。。。。。。。。。。。。。。。。。

代码:

#include<queue>
#include<cstdio>
#include<cstring>

#define maxn 15000
#define maxc 1000005
#define For(a, b, c) for(a = b; a <= (int)(c); ++a)
using namespace std;
int n;
char T[maxc], P[151][71];
inline int idx(char c){ return c - 'a'; }

struct Trie{
    int sz, ch[maxn][26], val[maxn];
    inline void init(){
        sz = 0;
        memset(ch, 0, sizeof(ch));
        memset(val, 0, sizeof(val));
    }
    inline void insert(char *s, int v){
        int i, u = 0, l = strlen(s);
        For(i, 0, l - 1){
            int c = idx(s[i]);
            if(!ch[u][c]) ch[u][c] = ++sz;
            u = ch[u][c];
        }
        val[u] = v;
    }
}tr;

struct AC_machine{
    int fail[maxn], last[maxn], cnt[maxn];
    inline void init(){
        memset(fail, 0, sizeof(fail));
        memset(last, 0, sizeof(last));
        memset(cnt, 0, sizeof(cnt));
    }
    inline void getfail(){
        int c, u, k, r;
        queue<int> q;
        fail[0] = 0;
        For(c, 0, 25){
            if(tr.ch[0][c]) q.push(tr.ch[0][c]);
        }
        while(!q.empty()){
            r = q.front(), q.pop();
            For(c, 0, 25){
                u = tr.ch[r][c];
                if(!u){ tr.ch[r][c] = tr.ch[fail[r]][c]; continue; }
                q.push(u);
                k = fail[r];
                while(k && !tr.ch[k][c]) k = fail[k];
                fail[u] = tr.ch[k][c];
                last[u] = tr.val[fail[u]] ? fail[u] : last[fail[u]];
            }
        }
    }
    inline void calc(int x){
        while(x){
            ++cnt[tr.val[x]];
            x = last[x];
        }
    }
    inline void find(char *s){
        int i, j, l = strlen(s);
        For(i, 0, l - 1){
            j = tr.ch[j][idx(s[i])];
            if(tr.val[j]) calc(j);
            else if(last[j]) calc(last[j]);
        }
    }
}ac;

int main(){
    int i;
    while(scanf("%d", &n), n){
        tr.init();
        ac.init();
        For(i, 1, n) scanf("%s", P[i]), tr.insert(P[i], i);
        scanf("%s", T);
        ac.getfail();
        ac.find(T);
        int best = -1;
        For(i, 1, n) if(ac.cnt[i] > best) best = ac.cnt[i];
        printf("%d\n", best);
        For(i, 1, n) if(ac.cnt[i] == best){
            printf("%s\n", P[i]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值