단어 쿼리
주제 링크 : ybt 효율적인 고급 2-5-1
일반적인 생각
많은 단어가 있고 또 다른 문장이 있습니다.
이 문장에서 몇 개의 단어가 하위 문자열로 나타 났는지 물어보십시오.
여러 데이터 세트.
아이디어
AC automata 템플릿 질문.
나는 전에 그것을 썼고 말할 것이 없습니다. 템플릿으로 이동하십시오.
암호
#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;
}