洛谷-P3796-【模板】AC自动机(加强版)

题目传送门

-------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题

sol:AC自动机,在fail边的基础上再加一个last边,指向真正有效的节点,跳fail边改成跳last边来跳过无效点。

  • AC自动机
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MAXN = 11000;
    struct Trie {
        int son[MAXN][26], fail[MAXN], last[MAXN];
        int cnt[MAXN], inde[MAXN]; int tot, root, _max;
        vector<int> vec; string str[160];
        int add_node() {
            memset(son[tot], -1, sizeof(son[tot]));
            cnt[tot] = 0; inde[tot] = -1;
            return tot ++;
        }
        void init() {
            tot = _max = 0;
            root = add_node();
        }
        void insert(char* s, int id) {
            int p = root;
            for (int i = 0; s[i]; i++) {
                int index = s[i] - 'a';
                if (son[p][index] == -1)
                    son[p][index] = add_node();
                p = son[p][index];
            }
            inde[p] = id;
            str[id] = s;
        }
        void build() {
            queue<int> que;
            fail[root] = last[root] = root;
            for (int i = 0; i < 26; i++) {
                if (son[root][i] == -1) son[root][i] = root;
                else {
                    fail[son[root][i]] = root;
                    last[son[root][i]] = root;
                    que.push(son[root][i]);
                }
            }
            while (!que.empty()) {
                int p = que.front(); que.pop();
                for (int i = 0; i < 26; i++) {
                    if (son[p][i] == -1) son[p][i] = son[fail[p]][i];
                    else {
                        fail[son[p][i]] = son[fail[p]][i];
                        if (inde[son[fail[p]][i]] != -1)
                            last[son[p][i]] = son[fail[p]][i];
                        else
                            last[son[p][i]] = son[last[p]][i];
                        que.push(son[p][i]);
                    }
                }
            }
        }
        void slove(char* s) {
            int p = root;
            for (int i = 0; s[i]; i++) {
                int index = s[i] - 'a';
                p = son[p][index];
                for (int tmp = p; tmp != root; tmp = last[tmp]) {
                    if (inde[tmp] == -1) continue;
                    cnt[tmp] ++;
                    if (cnt[tmp] > _max) {
                        _max = cnt[tmp];
                        vec.clear();
                        vec.push_back(inde[tmp]);
                    } else if (cnt[tmp] == _max) {
                        vec.push_back(inde[tmp]);
                    }
                }
            }
        }
        void output() {
            printf("%d\n", _max);
            sort(vec.begin(), vec.end());
            for (int i = 0; i < vec.size(); i++)
                cout << str[vec[i]] << endl;
        }
    } ac;
    char s[1000010];
    int main() {
        int n;
        while (scanf("%d", &n) && n) {
            ac.init();
            for (int i = 1; i <= n; i++) {
                scanf("%s", s);
                ac.insert(s, i);
            }
            ac.build(); scanf("%s", s);
            ac.slove(s); ac.output();
        }
        return 0;
    }

     

posted @ 2020-01-25 19:35  Jathon-cnblogs  阅读(184)  评论(0编辑  收藏  举报