题目大意:给出一些单词,和一个句子,问有多少个单词在句子中出现过。
思路:来签到吧
CODE:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define P(a) ((a) - 'a')
#define MAX 60
#define _MAX 1000010
using namespace std;
char s[_MAX];
struct Trie{
Trie *son[26],*fail;
int cnt;
Trie() {
memset(son,NULL,sizeof(son));
fail = NULL;
cnt = 0;
}
void Insert(char *s) {
Trie *now = this;
while(*s != '\0') {
if(now->son[P(*s)] == NULL)
now->son[P(*s)] = new Trie();
now = now->son[P(*s)];
++s;
}
++now->cnt;
}
}*root;
struct AC_Automaton{
void Build(int cnt) {
static char s[MAX];
for(int i = 1; i <= cnt; ++i) {
scanf("%s",s);
root->Insert(s);
}
static queue<Trie *> q;
while(!q.empty()) q.pop();
for(int i = 0; i < 26; ++i)
if(root->son[i] != NULL)
root->son[i]->fail = root,q.push(root->son[i]);
while(!q.empty()) {
Trie *now = q.front(); q.pop();
for(int i = 0; i < 26; ++i)
if(now->son[i] != NULL) {
Trie *temp = now->fail;
while(temp != root && temp->son[i] == NULL)
temp = temp->fail;
if(temp->son[i] != NULL) temp = temp->son[i];
now->son[i]->fail = temp;
q.push(now->son[i]);
}
}
}
int Ask(char *s) {
int re = 0;
Trie *now = root;
while(*s != '\0') {
while(now != root && now->son[P(*s)] == NULL)
now = now->fail;
if(now->son[P(*s)] != NULL)
now = now->son[P(*s)];
for(Trie *temp = now; temp != root; temp = temp->fail)
re += temp->cnt,temp->cnt = 0;
++s;
}
return re;
}
}solver;
int cases,cnt;
int main()
{
for(cin >> cases; cases--;) {
root = new Trie();
scanf("%d",&cnt);
solver.Build(cnt);
scanf("%s",s);
printf("%d\n",solver.Ask(s));
}
return 0;
}