Dominating Patterns (AC 自动鸡模版题, 出现次数最多的子串)

传送门

题意: 给你n个模式串, 再给你一个 文本串,问模式串在文本串中出现次数最多是多少。

   出现次数最多的模式串有哪些。

解: 模版题。

#include <bits/stdc++.h>
#define LL long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define mem(i, j) memset(i, j, sizeof(i))
using namespace std;
const int N = 150 * 70 + 5, M = 26;
map<string, int> vis;
char s[1000005], b[155][100];
struct Trie {
    int a[N][M], tot, val[N], Fail[N], last[N];
    ///last[j]:节点j沿着失配指针往回走时,遇到的下一个单词节点的编号 
    void init() {
        mem(a[0], -1); tot = 1; val[0] = -1; last[0] = 0;
    }
    int get(char Q) {
        return Q - 'a';
    }
    void join(char s[], int v) {
        int len = strlen(s); int now = 0;
        rep(i, 0, len - 1) {
            int id = get(s[i]);
            if(a[now][id] == -1) {
                mem(a[tot], -1);
                val[tot] = -1;
                a[now][id] = tot++;
            }
            now = a[now][id];
        }
        val[now] = v;
    }
    void getFail() {
        queue<int>Q;  while(!Q.empty()) Q.pop();
        Fail[0] = 0;
        rep(i, 0, M - 1) {
            if(a[0][i] == -1) a[0][i] = 0;
            else {
                Fail[a[0][i]] = 0;
                Q.push(a[0][i]);
                last[a[0][i]] = 0;
            }
        }
        while(!Q.empty()) {
            int now = Q.front(); Q.pop();
            rep(i, 0, M - 1) {
                int u = a[now][i];
                if(a[now][i] == -1) a[now][i] = a[Fail[now]][i];
                else {
                    Fail[u] = a[Fail[now]][i];
                    Q.push(u);
                    last[u] = val[Fail[u]] == -1 ? last[Fail[u]] : Fail[u];
                }
            }
        }
    }
    int num[155];
    void print(int x) {
        if(x) {
            num[val[x]]++;
            print(last[x]);
        }
    }
    void query(char s[], int n) {
        mem(num, 0);
        int len = strlen(s);
        int now = 0;
        rep(i, 0, len - 1) {
            now = a[now][get(s[i])];
            if(val[now] != -1) print(now);
            else if(last[now] != -1) print(last[now]);
        }
        int ma = 0;
        rep(i, 1, n) {
            ma = max(ma, num[i]);
        }
        printf("%d\n", ma);
        rep(i, 1, n) {
            if(num[vis[b[i]]] == ma) {
                printf("%s\n", b[i]);
            }
        }
    }
};
Trie AC;
int main() {
    int n;
    while(scanf("%d", &n) && n) {
        AC.init(); vis.clear();
        rep(i, 1, n) {
            scanf("%s", b[i]);
            AC.join(b[i], i);
            vis[b[i]] = i;
        }
        AC.getFail();
        scanf("%s", s);
        AC.query(s, n);
    }
    return 0;
}
View Code

 

 

posted on 2019-12-07 11:50  Willems  阅读(215)  评论(0编辑  收藏  举报

导航