时间复杂度:\(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
分别求出每个模式串在文本串中出现的次数。