hdu 2222 Keywords Search
Keywords Search
AC自动机典型模板
/*
写于13年4月1日,AC自动机练习
参考的别人代码,
个人觉得自动机就是trie 外加kmp的有机组合
*/
#include<string.h>
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=10010*50;
char str[1000010];//文本串
struct node{
node *fail;
node *next[26];
int flag;
node()
{
fail=NULL;
flag=0;
for(int i=0;i<26;i++)
{
next[i]=NULL;
}
}
}*root;
node *q[maxn];//队列
void insert(char *s)//建树
{
node *p=root;
int k=0;
while(s[k]!='\0')
{
int temp=s[k]-'a';
if(p->next[temp]==NULL)
p->next[temp]=new node;
p=p->next[temp];
k++;
}
p->flag++;//单词个数
}
void build_fail()//建立失败指针 BFS
{
node *p,*temp;
int head=0,tail=0;
q[tail++]=root;
while(tail^head)//队列中存在元素
{
p=q[head++];
temp=NULL;
for(int i=0;i<26;i++)
{
if(p->next[i]!=NULL)//对p的每个儿子寻找fail
{
if(p==root)//根的子节点的失败指针指向根节点
{
p->next[i]->fail=root;
}
else
{
temp=p->fail;//p的fail
while(temp!=NULL)//匹配成功或者temp为空
{
if(temp->next[i]!=NULL)
{
p->next[i]->fail=temp->next[i];//p的儿子与fail的儿子相同,匹配成功
break;
}
temp=temp->fail;
}
if(temp==NULL)//匹配失败,从头开始
{
p->next[i]->fail=root;
}
}
q[tail++]=p->next[i];//p的儿子入队
}
}
}
}
int query()
{
node *p,*temp;
int k,ans=0;
p=root;
int len=strlen(str);
for(int i=0;i<len;i++)
{
k=str[i]-'a';
while(p->next[k]==NULL&&p!=root)//跳转失败指针
{
p=p->fail;
}
p=p->next[k];
if(p==NULL)
p=root;
temp=p;
//p不变,temp计算后缀
//temp等于root时,后缀为空
//temp->flag=-1时,有循环体知,后续fail->flag全部为-1
while(temp!=root&&temp->flag!=-1)
{
ans+=temp->flag;
temp->flag=-1;
temp=temp->fail;
}
}
return ans;
}
int main()
{
char key[55];
int ncase,num;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&num);
//getchar();
root=new node;
while(num--)
{
scanf("%s",key);
insert(key);
}
build_fail();
scanf("%s",str);
printf("%d\n",query());
}
return 0;
}