指针AC自动机球跳!
  • 板块学术版
  • 楼主Link_Cut_Y
  • 当前回复13
  • 已保存回复13
  • 发布时间2023/6/21 17:07
  • 上次更新2023/11/3 13:25:41
查看原帖
指针AC自动机球跳!
519384
Link_Cut_Y楼主2023/6/21 17:07

悬关一个。

题目大意是求有多少个模板串在模式串中出现了。多测。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

int n, T;
struct node {
    node *s[26];
    node *fail;
    bool appear;
    node() {
        for (int i = 0; i < 26; i ++ ) 
            s[i] = nullptr;
        fail = nullptr; appear = false;
    }
    ~node() {};
    
    void insert(string str) {
        auto now = this;
        for (auto i : str) {
            int v = i - 'a';
            if (now -> s[v] == nullptr)
                now -> s[v] = new node();
            now = now -> s[v];
        }
        now -> appear = true;
    }
    
    void get_fail() {
        queue<node*> q; q.push(this);
        while (q.size()) {
            auto t = q.front(); q.pop();
            for (int i = 0; i < 26; i ++ ) {
                if (t -> s[i] == nullptr) continue;
                q.push(t -> s[i]);
                auto fa = t -> fail;
                if (t == this) { // 是根节点出边的,fail 指针都指向根节点
                    t -> s[i] -> fail = this;
                    continue;
                }
                while (fa) {
                    if (fa -> s[i]) {
                        t -> s[i] -> fail = fa -> s[i];
                        break;
                    }
                    fa = fa -> fail;
                }
                if (fa == nullptr) t -> s[i] -> fail = this;
            }
        }
    }
    
    int AC(string text) {
        auto now = this; int ans = 0;
        for (auto i : text) {
            int v = i - 'a';
            while (now != nullptr and now -> s[v] == nullptr) now = now -> fail;
            if (now == nullptr) { now = this; continue; }
            now = now -> s[v];
            auto tmp = now;
            while (tmp != this) {
                if (tmp -> appear) {
                    ans ++ ;
                    tmp -> appear = false;
                }
                else break;
                tmp = tmp -> fail;
            }
        }
        return ans;
    }
    void clear() {
        queue<node*> q; q.push(this);
        vector<node*> states;
        while (q.size()) {
            auto t = q.front(); q.pop();
            states.push_back(t);
            for (int i = 0; i < 26; i ++ ) {
                if (t -> s[i] == nullptr) continue;
                q.push(t -> s[i]);
            }
        }
        for (auto t : states) {
            if (t == this) continue;
            if (t == nullptr) continue;
            t = nullptr;
        }
    }
};

int main() {
    cin.tie(nullptr) -> sync_with_stdio(false);
    cin >> T; node root;
    while (T -- ) {
        cin >> n;
        for (int i = 1; i <= n; i ++ ) {
            string str; cin >> str;
            root.insert(str);
        }
        root.get_fail();
        string text; cin >> text;
        cout << root.AC(text) << endl;
        root.clear();
    }
    return 0;
}
2023/6/21 17:07
加载中...