HDU2896 病毒侵袭 AC自动机

来源:互联网 发布:设计模式php 编辑:程序博客网 时间:2024/05/01 08:55

题目大意:给出n个病毒和n个网站,找出每一个网站中含有的病毒种类,并按病毒编号升序输出,最后统计含有病毒的网站个数。


分析:比较裸的AC自动机的题,我们可以在构造tire树的过程中顺便把编号插入,然后询问时纪录病毒个数的同时用一个数组纪录病毒的编号,然后排序输出即可(WA若干次才发现忘把病毒按编号排序后再输出了)。还有就是本题空间卡的很死,你要是按题意(每一个字符都是课件的ASC2可见代码)256来开tire树的话肯定会MLE,试了几次之后发现开到130就可以了。



实现代码如下:

#include <cstdio>#include <cstring>#include <iostream>#include <queue>#include <algorithm>using namespace std;#define son_num 130#define maxn 10010struct node{    int code;    int terminal;    node *fail;    node *next[son_num];    node()    {        fail=NULL;        code=0;        terminal=0;        memset(next,NULL,sizeof(next));    }};int ans[5]; //纪录主串含有的病毒的编号//构建Tire树void insert(node *root,char *str,int x) //x为该病毒的编号{    node *p=root;    int i=0,index;    while(str[i])    {        index=str[i];        if(p->next[index]==NULL)          p->next[index]=new node();        p=p->next[index];        i++;    }    p->code=x;    p->terminal=1;}//寻找失败指针void build_fail(node *root){    queue <node *> que;    root->fail=NULL;    que.push(root);    while(!que.empty())    {        node *temp=que.front();        que.pop();        node *p=NULL;        for(int i=0;i<son_num;i++)        {            if(temp->next[i]!=NULL)            {                if(temp==root) temp->next[i]->fail=root;                else{                p=temp->fail;                while(p!=NULL)                {                    if(p->next[i]!=NULL)                    {                        temp->next[i]->fail=p->next[i];                        break;                    }                    p=p->fail;                }                if(p==NULL)                  temp->next[i]->fail=root;}                que.push(temp->next[i]);            }        }    }}//询问主串中含有多少个关键字int query(node *root,char *str){    int i=0,cnt=0,index,len;    len=strlen(str);    node *p=root;    while(str[i])    {        index=str[i];        while(p->next[index]==NULL&&p!=root)          p=p->fail;        p=p->next[index];        if(p==NULL) p=root;        node *temp=p;        while(temp!=root&&temp->code)        {            ans[cnt]=temp->code;            cnt+=p->terminal;            temp=temp->fail;        }        i++;    }    return cnt;}int main(){    int n,m;    char str[205];    char web[maxn];    while(scanf("%d",&n)!=-1)    {        node *root=new node();        for(int i=1;i<=n;i++)        {            scanf("%s",str);            insert(root,str,i);        }        build_fail(root);        int cnt=0; //纪录有多少个网站含有病毒        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            scanf("%s",web);            bool flag=false; //标记该网站是否含有病毒            int num=query(root,web);            if(num)            {                flag=true;                printf("web %d:",i);                sort(ans,ans+num);                for(int j=0;j<num;j++)                  printf(" %d",ans[j]);                printf("\n");            }            if(flag) cnt++;        }        printf("total: %d\n",cnt);    }    return 0;}


0 0