您的位置:首页 > 其它

hdoj 2222-Keywords Search解题报告

2012-05-07 00:09 211 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222

AC自动机,用于这种在一个串中同时查找几个子串的出现个数,这是一道模板题,所以很有保存的价值,具体的ac自动机的匹配原理http://www.cppblog.com/mythit/archive/2009/04/21/80633.html

View Code

#include<stdio.h>
#include<string.h>
struct node
{
int cnt;
node *next[26],*fail;
}*rt,qq[500005],*que[500005];//不去新建节点,而是用qq数组去存储,节省时间
char key[55];
char mes[1000005];
int k;
void insert(char *str)//创建字典树的过程
{
int i;
int temp;
node *p=rt;
for(i=0;str[i];i++)
{
temp=str[i]-'a';
if(p->next[temp]==NULL)
{
qq[k].cnt=0;
qq[k].fail=NULL;
memset(qq[k].next,NULL,sizeof(qq[k].next));
p->next[temp]=&qq[k++];
}
p=p->next[temp];
}
p->cnt++;
}
void ac()//类似于kmp的getnext函数
{
int f=0,r=0;
int i;
node *p,*temp;
rt->fail=NULL;
que[r++]=rt;
while(f<r)
{
temp=que[f++];
for(i=0;i<26;i++)
{
if(temp->next[i]==NULL)
continue;
if(temp==rt)
temp->next[i]->fail=rt;
else
{
for(p=temp->fail;p!=NULL;p=p->fail)
{
if(p->next[i]!=NULL)
{
temp->next[i]->fail=p->next[i];
break;
}
}
if(p==NULL)
{
temp->next[i]->fail=rt;
}
}
que[r++]=temp->next[i];
}
}
}
int acs()
{
int ans=0;
int i,id;
node *p=rt,*temp;
for(i=0;mes[i];i++)
{
id=mes[i]-'a';
while(p->next[id]==NULL&&p!=rt)
p=p->fail;
p=p->next[id];
if(p==NULL)
p=rt;
for(temp=p;temp!=NULL&&temp->cnt!=-1;temp=temp->fail)
{
ans+=temp->cnt;
temp->cnt=-1;
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
int n;
int i,j;
while(t--)
{
k=0;
rt=&qq[k++];
memset(rt->next,NULL,sizeof(rt->next));
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",key);
insert(key);
}
ac();
scanf("%s",mes);
printf("%d\n",acs());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: