AC自动机

文本串中出现次数最多的模式串

//LA4670, 洛谷3796
%:pragma GCC optimize("Ofast", 2)
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 12005
int t, n, m, len, ans;
int cnt[155], fail[maxn];
int val[maxn], ch[maxn][26];
char text[1000005], s[155][80];
void init(){
    ans = 0;
    memset(ch, 0, sizeof(ch));
    fill(fail, fail+maxn, 0);
    fill(val, val+maxn, 0);
    fill(cnt, cnt+155, 0);
}
void s_insert(char *s, int v){ //构建字典树
    int now, root = 0;
    len = strlen(s);
    for(int i = 0; i < len; i ++){
        now = s[i]-'a';
        if(!ch[root][now]){
            ch[root][now] = ++ans;
        }
        root = ch[root][now];
    }
    val[root] = v;
}
void get_fail(){ //获取失配指针
    queue<int>Q;
    int u, now = 0;
    for(int i = 0; i < 26; i ++){
        if(ch[now][i]){ //将模式串的首字母序号加入队列
            Q.push(ch[now][i]);
            //fail[ch[now][i]] = 0;
            //last[ch[now][i]] = 0;
        }
    }
    while(!Q.empty()){
        now = Q.front(); Q.pop();
        for(int i = 0; i < 26; i ++){
            u = ch[now][i];
            if(u){ //当前序列存在
                fail[u] = ch[fail[now]][i]; //失配指针指向其父节点失配指针指向节点的子节点
                Q.push(ch[now][i]);
            }else{
                ch[now][i] = ch[fail[now]][i]; //指向失配指针指向节点子节点
            }
        }
    }
}
void query(char *text){
    len = strlen(text);
    int now = 0;
    for(int i = 0; i < len; i ++){
        now = ch[now][text[i]-'a'];
        for(int j = now; j; j = fail[j]){
            cnt[val[j]]++;
        }
    }
}
int main(){
    while(scanf("%d", &n) && n){
        init();
        for(int i = 1; i <= n; i ++){
            scanf("%s", s[i]);
            s_insert(s[i], i);
        }
        scanf("%s", text);
        get_fail();
        query(text);
        int res = 0;
        for(int i = 1; i <= n; i ++){
            res = max(res, cnt[i]);
        }
        printf("%d
", res);
        for(int i = 1; i <= n; i ++){
            if(cnt[i] == res)
                printf("%s
", s[i]);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/microcodes/p/12319330.html