AC自动机

朴素AC自动机拓扑排序优化板子
求匹配次数:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, fail[N], tr[N][26], tot, du[N], tans[N], id[N], ans[N];
string s[N], t;
void build() {
    queue<int> q;
    for (int i = 0; i < 26; i++) 
        if (tr[0][i]) q.push(tr[0][i]);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = 0; i < 26; i++) {
            if (tr[u][i]) {
                q.push(tr[u][i]);
                fail[tr[u][i]] = tr[fail[u]][i];
                du[tr[fail[u]][i]]++; // topology排序优化
            }
            else 
                tr[u][i] = tr[fail[u]][i];
        }
    }
}
int query(string t) {
    int u = 0, res = 0;
    for (int i = 0; i < t.size(); i++) {
        u = tr[u][t[i] - 'a'];
        //以下部分可用拓扑排序优化
        // for (int j = u; j && ed[j]; j = fail[j]) {
        //     res += ed[j]; ed[j] = 0;
        // }
        tans[u]++;
    }
    return res;
}
void topu() {
    queue<int>q;
    for (int i = 0; i <= tot; i++) {
        if (du[i] == 0) q.push(i);
    }
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        int v = fail[u];
        tans[v] += tans[u];
        if (!(--du[v])) q.push(v);
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s[i];
        int x = 0;
        for (int j = 0; j < s[i].size(); j++) {
            if (tr[x][s[i][j] - 'a']) x = tr[x][s[i][j] - 'a'];
            else tr[x][s[i][j] - 'a'] = ++tot, x = tot;
        }   
        idx[i] = x;
    }
    cin >> t;
    build();
    query(t);
    topu();
    for (int i = 1; i <= n; i++) cout << tans[idx[i]] << '\n';
}
posted @ 2025-03-09 19:41  lyrrr  阅读(23)  评论(0)    收藏  举报