//可能有重复单词
# include <stdio.h>
# include <queue>
# include <string.h>
# include <algorithm>
using namespace std;
char str[110],a[1000010];
# define kind 26
struct node
{
node *fail;
node *next[kind];
int cnt;//从根到此处是否是关键字,并且记录是多少个关键字的结尾
node()
{
fail=NULL;
cnt=0;
for(int i=0;i<26;i++)
next[i]=NULL;
// memset(next,0,sizeof(next));
}
};
queue<node*>qq;
void Buildtree(node *root ,int index)
{
node *p=root;
int i=0,id;
while(str[i])
{
id=str[i]-'a';
if(p->next[id]==NULL)
p->next[id]=new node();
p=p->next[id];
i++;
}
(p->cnt)++;///记录是多少个关键字的结尾
}
void bfs(node *root)
{
while(!qq.empty())
qq.pop();
root->fail=NULL;
qq.push(root);
root->fail=NULL;
node *tmp,*p;
while(!qq.empty())
{
tmp=qq.front();
qq.pop();
p=NULL;
for(int i=0;i<kind;i++)
{
if(tmp->next[i]!=NULL)
{
p=tmp->fail;
while(p&&!p->next[i])
p=p->fail;
if(!p)
tmp->next[i]->fail=root;
else
tmp->next[i]->fail=p->next[i];
qq.push(tmp->next[i]);
}
}
}
}
int has[10010];
int Ac_run(node *root)
{
int i=0,ans=0,id;
node *p=root;
while(a[i])
{
id=a[i]-'a';
while(!p->next[id]&&p!=root)//跳转失败指针
p=p->fail;
p=p->next[id];
if(!p)
p=root;
node *tmp=p;//p不动,temp计算后缀串
while(tmp!=root&&tmp->cnt!=-1)
{
ans+=tmp->cnt;
tmp->cnt=-1;///
// has[tmp->cnt]=1;
tmp=tmp->fail;
}
i++;
}
return ans;
}
int main()
{
int t,n;
while(~scanf("%d",&t))
{
while(t--)
{
node *root=new node();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",str);
Buildtree(root,i);
}
bfs(root);
// memset(has,0,sizeof(has));
scanf("%s",a);
printf("%d\n",Ac_run(root));
}
}
return 0;
}
hdu 2222 Keywords Search (AC自动机)
最新推荐文章于 2024-04-26 20:01:35 发布