#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n;
namespace AC {
int tr[N][26], tot;
int e[N], fail[N];
void insert(char *s) {
int u = 0;
for (int i = 1; s[i]; i++) {
if (!tr[u][s[i] - 'a']) tr[u][s[i] - 'a'] = ++tot;
u = tr[u][s[i] - 'a'];
}
e[u]++;
}
queue<int> q;
void build() {
for (int i = 0; i < 26; i++)
if (tr[0][i]) q.push(tr[0][i]);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if (tr[u][i])
fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
else
tr[u][i] = tr[fail[u]][i];
}
}
}
int query(char *t) {
int u = 0, res = 0;
for (int i = 1; t[i]; i++) {
u = tr[u][t[i] - 'a']; // 转移
for (int j = u; j && e[j] != -1; j = fail[j]) {
res += e[j], e[j] = -1;
}
}
return res;
}
void init(){
memset(e,0,sizeof e);
memset(fail,0,sizeof fail);
memset(tr,0,sizeof tr);
tot=0;
}
} // namespace AC
char s[N];int T;
int main() {
scanf("%d",&T);
while(T--){
AC::init();
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%s", s + 1), AC::insert(s);
scanf("%s", s + 1);
AC::build();
printf("%d\n", AC::query(s));
// return 0;
}
}
Keywords Search(ac自动机
最新推荐文章于 2022-03-14 18:13:28 发布
本文介绍了如何使用C++实现字符串插入操作,并利用自动机(Automata)构建AC自动机进行高效查询。通过AC自动机,作者展示了如何在大规模数据中快速查询字符串出现频率。涉及的主要技术包括字符数组、队列和失败链接算法。

273

被折叠的 条评论
为什么被折叠?



