时间复杂度:\(O(s * n(建树) + s * n(失配指针) + t * s(查询最坏的时候) )\)

https://www.luogu.com.cn/problem/P3808

求有多少个不同的模式串在文本串里出现过。两个模式串不同当且仅当他们编号不同。

#include<bits/stdc++.h>
using namespace std;
using LL = long long;
struct ACAutomaton{
	static constexpr int N = 1e6 + 10;
	int ch[N][26], fail[N], cntNodes;
	int cnt[N];
	ACAutomaton(){
		cntNodes = 1;
	}
	void insert(string s){
		int u = 1;
		for (auto c : s){
			int &v = ch[u][c - 'a'];
			if (!v) v = ++ cntNodes;
			u = v;
		}
		cnt[u] ++ ;
	}
	void build(){
		fill(ch[0], ch[0] + 26, 1);
		queue<int> q;
		q.push(1);
		while (!q.empty()){
			int u = q.front();
			q.pop();
			for (int i = 0; i < 26; i ++ ){
				int &v = ch[u][i];
				if (!v) v = ch[fail[u]][i];
				else{
					fail[v] = ch[fail[u]][i];
					q.push(v);
				}
			}
		}
	}
	LL query(string t){
		LL ans = 0;
		int u = 1;
		for (auto c : t){
			u = ch[u][c - 'a'];
			for (int v = u; v && ~ cnt[v]; v = fail[v]){
				ans += cnt[v];
				cnt[v] = -1;
			}
		}
		return ans;
	}
};
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n;
	cin >> n;
	ACAutomaton aca;
	for (int i = 0; i < n; i ++ ){
		string t;
		cin >> t;
		aca.insert(t);
	}
	aca.build();
	string s;
	cin >> s;
	cout << aca.query(s) << "\n";
	return 0;
}

https://www.luogu.com.cn/problem/P3796
找出哪些模式串在文本串中出现的次数最多。

https://www.luogu.com.cn/problem/P5357
分别求出每个模式串​在文本串中出现的次数。

posted on 2022-06-07 22:31  Hamine  阅读(31)  评论(0编辑  收藏  举报