AC自动机板子

#include <bits/stdc++.h>
#define ll long long
using namespace std;
/*
	ac自动机板子
	1.建树 insert
	2.建自动机 build
	3.查询模式串出现个数 query

	ch[i][j]: 树上节点为i,指向子节点边为j的子树节点
	cnt[i]: 树上节点为i为结束的模式串的个数
	ne[i]: i点的回跳边
	ch[i][j]: i点边为j的树边/转移边
*/
const int N = 1000001;
int n;
string s, t;
int ch[N][26], idx, cnt[N];
int ne[N];

void insert(string &str); //建trie树
void build(); //建自动机
int query(string &str); //在str里找有多少个模式串作为字串出现过
void solve();

int query(string &str) {
	int ans = 0;
	for (int k = 0, i = 0; k < str.size(); k++) {
		i = ch[i][str[k] - 'a'];
		for (int j = i; j && ~cnt[j]; j = ne[j]) {
			ans += cnt[j];
			cnt[j] = -1;
		}
	}
	return ans;
}

void build() {
	queue<int> q;
	for (int i = 0; i < 26; i++) {
		if (ch[0][i])
			q.push(ch[0][i]);
	}
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = 0; i < 26; i++) {
			int v = ch[u][i];
			if (v) {
				ne[v] = ch[ne[u]][i];
				q.push(v);
			} else
				ch[u][i] = ch[ne[u]][i];
		}
	}
}

void insert(string &str) {
	int p = 0;
	for (int i = 0; i < str.size(); i++) {
		int j = str[i] - 'a';
		if (!ch[p][j])
			ch[p][j] = ++idx;
		p = ch[p][j];
	}
	cnt[p]++;
}

void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s;
		insert(s);
	}
	build();
	cin >> t;
	cout << query(t) << '\n';
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

	int T = 1;
//	cin >> T;
	while (T--) {
		solve();
	}
	return 0;
}
posted @ 2025-08-18 16:59  Gusare  阅读(7)  评论(0)    收藏  举报