洛谷-P3808-【模板】AC自动机(简单版)

题目传送门

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

sol:标准AC自动机,注意不能重复跳fail边,像"aaaaaaa...aaaaaaaa"这样的数据每跳一次fail边只往上走了一层。

  • AC自动机
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MAXN = 1e6 + 10;
    struct Trie {
        int son[MAXN][26], cnt[MAXN], fail[MAXN];
        int tot, root;
        int add_node() {
            int i = tot ++;
            memset(son[i], -1, sizeof(son[i]));
            cnt[i] = 0;
            return i;
        }
        void init() {
            tot = 0;
            root = add_node();
        }
        void insert(char* s) {
            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];
            }
            cnt[p] ++;
        }
        void build() {
            queue<int> que; fail[root] = root;
            for (int i = 0; i < 26; i++) {
                if (son[root][i] == -1) son[root][i] = root;
                else {
                    fail[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];
                        que.push(son[p][i]);
                    }
                }
            }
        }
        int slove(char* s) {
            int p = root, res = 0;
            for (int i = 0; s[i]; i++) {
                int index = s[i] - 'a';
                p = son[p][index];
                for (int tmp = p; tmp != root && cnt[tmp] != -1; tmp = fail[tmp]) {
                    res += cnt[tmp];
                    // 访问过就把cnt设置成-1,防止下次跳fail边重复进入
                    cnt[tmp] = -1;
                }
            }
            return res;
        }
    } ac;
    char s[MAXN];
    int main() {
        ac.init();
        int n; scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", s);
            ac.insert(s);
        }
        scanf("%s", s); ac.build();
        printf("%d\n", ac.slove(s));
        return 0;
    }

     

posted @ 2020-01-25 19:23  Angel_Demon  阅读(...)  评论(...编辑  收藏