单词查询
题目链接:ybt高效进阶2-5-1
题目大意
有一堆单词,然后又有一个句子。
问你有多少个单词在这个句子中作为一个子串出现过。
多组数据。
思路
AC 自动机模板题。
之前写过了,也没有什么好说的,直接上模板即可。
代码
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
struct Trie {
int son[30], num, fail;
bool use;
}tree[500001];
int T, tot, ans, n;
char c[51], s[1000001];
queue <int> q;
void csh() {
tot = 0;
ans = 0;
memset(tree, 0, sizeof(tree));
}
void insert_word() {
int size = strlen(c);
int now = 0;
for (int i = 0; i < size; i++) {
if (!tree[now].son[c[i] - 'a']) tree[now].son[c[i] - 'a'] = ++tot;
now = tree[now].son[c[i] - 'a'];
}
tree[now].num++;
}
void build_fail() {
for (int i = 0; i < 26; i++)
if (tree[0].son[i]) {
q.push(tree[0].son[i]);
tree[tree[0].son[i]].fail = 0;
}
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = 0; i < 26; i++)
if (tree[now].son[i]) {
q.push(tree[now].son[i]);
tree[tree[now].son[i]].fail = tree[tree[now].fail].son[i];
}
else tree[now].son[i] = tree[tree[now].fail].son[i];
}
}
void get_AC() {
int now = 0;
int size = strlen(s);
for (int i = 0; i < size; i++) {
now = tree[now].son[s[i] - 'a'];
int noww = now;
while (noww && !tree[noww].use) {
ans += tree[noww].num;
tree[noww].use = 1;
noww = tree[noww].fail;
}
}
}
int main() {
scanf("%d", &T);
while (T--) {
csh();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", &c);
insert_word();
}
scanf("%s", &s);
build_fail();
get_AC();
printf("%d\n", ans);
}
return 0;
}