#include <bits/stdc++.h>
using namespace std;
struct Tree
{
Tree *next[26];
Tree *fail;
int count;
Tree(){
for(int i=0;i<26;++i){
next[i]=NULL;
}
fail=NULL;
count=0;
}
};
char target[1000000];
void insert(Tree *p,char words[])
{
int i=0;
while(words[i]){
int k=words[i++]-'a';
if(p->next[k]==NULL)
p->next[k]=new Tree();
p=p->next[k];
}
p->count++;
}
void buildAC(Tree *r)
{
queue<Tree*> q;
q.push(r);
while(!q.empty()){
Tree *s=q.front();
q.pop();
for(int i=0;i<26;++i){
if(s->next[i]){
if(s==r) s->next[i]->fail=r;//s为根节点,则将后代next的fail指向r
else{
Tree *p=s->fail;
while(p){
if(p->next[i]){//有相同的后缀边
s->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(!p) s->next[i]->fail=r;//没有相同后缀边,失效时指向r
}
q.push(s->next[i]);
}
}
}
}
int search(Tree *r)
{
int i=0,cut=0;
Tree *p=r;
while(target[i]){
int k=target[i++]-'a';
while(!p->next[k]&&p!=r) p=p->fail;//跳转到失效指针
p=p->next[k];
if(p==NULL) p=r;
Tree *t=p;
while(t!=r&&t->count!=-1){
cut+=t->count;
t->count=-1;
t=t->fail;
}
}
return cut;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
Tree r;
int n;
scanf("%d",&n);
while(n--){
char words[64];
scanf("%s",words);
insert(&r,words);
}
buildAC(&r);
scanf("%s",target);
printf("%d\n",search(&r));
}
return 0;
}
hdu2222 Keywords Search(AC自动机)
猜你喜欢
转载自blog.csdn.net/gl486546/article/details/79834684
今日推荐
周排行