您的位置:首页 > 其它

hdu 3065 病毒侵袭持续中 AC自动机

2015-03-30 21:11 465 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065

小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?

[align=left]Input[/align]
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
[align=left]Output[/align]
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码:
出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。

题意描述:中文题,如上所述。
算法分析:AC自动机的简单题,大白书和很多博客都有AC自动机的详细介绍。AC自动机真心是个字符串处理的神奇东西,好好学习一下。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define inf 0x7fffffff
#define PI 3.141592654
#define exp 1e-10
using namespace std;
const int maxn=1000+10;
const int M = 2000000+10;

struct node
{
node *fail;
node *child[26];
int count;
int id;
node () {
fail=NULL;
count=0;
id=-1;
memset(child,NULL,sizeof(child));
}
}*q[50000+100];
int head,tail;
int n;
char keyword[maxn][55];
int an[maxn];
char str[M];

void insert(node *root,char *str,int k)
{
node *p=root;
int len=strlen(str);
for (int i=0 ;i<len ;i++)
{
int index=str[i]-'A';
if (p->child[index]==NULL) p->child[index]=new node();
p=p->child[index];
}
p->count++;
p->id=k;// no repeat
return ;
}
void build_AC(node *root)
{
root->fail=NULL;
q[head++]=root;
while (head != tail)
{
node *temp=q[tail++];
node *p=NULL;
for (int i=0 ;i<26 ;i++)
{
if (temp->child[i]!=NULL)
{
if (temp==root) temp->child[i]->fail=root;
else
{
p=temp->fail;
while (p!=NULL)
{
if (p->child[i]!=NULL)
{
temp->child[i]->fail=p->child[i];
break;
}
p=p->fail;
}
if (p==NULL) temp->child[i]->fail=root;
}
q[head++]=temp->child[i];
}
}
}
return ;
}
void find(node *root,char *str)
{
int len=strlen(str);
node *p=root;
for (int i=0 ;i<len ;i++)
{
if (str[i]>='A' && str[i]<='Z')
{
int index=str[i]-'A';
while (p->child[index]==NULL && p!=root) p=p->fail;
p=p->child[index];
p= p==NULL ? root : p ;
node *temp=p;
while (temp!=root)
{
if (temp->count) an[temp->id ]++;
temp=temp->fail;
}
}
else p=root;
}
return ;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
head=tail=0;
memset(str,0,sizeof(str));
memset(keyword,0,sizeof(keyword));
memset(an,0,sizeof(an));
node *root=new node();

for (int i=0 ;i<n ;i++)
{
scanf("%s",keyword[i]);
insert(root,keyword[i],i);
}
build_AC(root);
getchar() ;gets(str) ;
find(root,str);
for (int i=0 ;i<n ;i++)
if (an[i]) printf("%s: %d\n",keyword[i],an[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: