HDU 3065 病毒侵袭持续中 (AC自动机)

时间:2022-12-05 00:21:30
///要求记录子串在匹配串重复出现的个数
# include <algorithm>
# include <stdio.h>
# include <queue>
# include <string.h>
using namespace std;
# define kind 128
struct node
{
node *fail;
node *next[kind];
int cnt;//是否为该单词的最后一个节点
// int index;
node()
{
cnt=0;
fail=NULL;
memset(next,NULL,sizeof(next));
}
};
char str[1010][55],a[2000010];
queue<node*>qq;
void Buildtree(node *root,int index)
{
node *p=root;
int i=0,id;
while(str[index][i])
{
id=str[index][i];
if(p->next[id]==NULL)
p->next[id]=new node();
p=p->next[id];
i++;
}
(p->cnt)=index;

}
void bfs(node *root)
{
while(!qq.empty())
qq.pop();
qq.push(root);
root->fail=NULL;
node *tmp,*p;
while(!qq.empty())
{
tmp=qq.front();
qq.pop();
p=NULL;
for(int i='A'; i<='Z'; 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[1010];
void Ac_run(node *root)
{
int i=0,ans=0,id;
node *p=root;
while(a[i])
{
id=a[i];
while(!p->next[id]&&p!=root)
p=p->fail;
p=p->next[id];
if(!p)
p=root;
node *tmp=p;
while(tmp!=root)
{
// tmp->cnt==-1 表示计算过 这题可重复计算
if(tmp->cnt)
has[tmp->cnt]++;
tmp=tmp->fail;
}
i++;
}
}
void del(node *p)///释放内存
{
for(int i=0;i<kind;i++)
{
if(p->next[i]!=NULL)
del(p->next[i]);
}
delete p;
}
int main()
{
int n,i;
while(~scanf("%d",&n))
{
node *root=new node();
for(i=1; i<=n; i++)
{
scanf("%s",str[i]);
Buildtree(root,i);
}
bfs(root);
memset(has,0,sizeof(has));
scanf("%s",a);
Ac_run(root);
del(root);
for(i=1; i<=n; i++)
{
if(has[i])
{
printf("%s: %d\n",str[i],has[i]);
}
}
}
return 0;
}