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';
}

浙公网安备 33010602011771号