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

病毒侵袭持续中

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16472    Accepted Submission(s): 5572


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

 

Input
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
 

 

Output
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
 

 

Sample Input
3 AA BB CC ooxxCC%dAAAoen....END
 

 

Sample Output
AA: 2 CC: 1
Hint
Hit: 题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。 计数策略也可一定程度上从Sample中推测。
 
 
  1 /* 
  2 hdu 3065 题意很简单 
  3 */  
  4 #include <iostream>   
  5 #include<string.h>  
  6 #include<stdlib.h>  
  7 using namespace std;   
  8     
  9 int biaoshi[1010];  
 10 char chuan[1100][55];  
 11 const int kind = 26; //!!!!!!!!!!!!!!!!!!  
 12   
 13 struct node{    
 14     node *fail;       //失败指针  
 15     node *next[kind];   
 16     int count;        //是否为该单词的最后一个节点  
 17     node(){           //构造函数初始化  
 18         fail=NULL;   
 19         count=0;   
 20         memset(next,NULL,sizeof(next));   
 21     }   
 22 }*q[50000];          //队列,方便用于bfs构造失败指针  
 23 char keyword[510];     //输入的单词  
 24 char str[2000010];    //模式串  
 25 int head,tail;        //队列的头尾指针  
 26     
 27 void insert(char *str,node *root,int no){   
 28     node *p=root;   
 29     int i=0,index;    
 30     while(str[i]){   
 31         index=str[i]-'A'; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
 32         if(p->next[index]==NULL) p->next[index]=new node();    
 33         p=p->next[index];  
 34         i++;  
 35     }   
 36     p->count=no;//初始化为0,++后为1,表示是一个单词的结尾!!!!!!!!!!!!!!!!!  
 37 }   
 38 void build_ac_automation(node *root)  
 39 {  
 40     int i;  
 41     root->fail=NULL;   
 42     q[head++]=root;   
 43     while(head!=tail)  
 44     {   
 45         node *temp=q[tail++];//拿到一个节点  
 46         node *p=NULL;   
 47         for(i=0;i<26;i++)//!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
 48         {   
 49             if(temp->next[i]!=NULL)//若其i孩子非空  
 50             {   
 51                 if(temp==root) //他自己是头,其孩子的失败指针指向头  
 52                     temp->next[i]->fail=root;                   
 53                 else{ //普通节点  
 54                     p=temp->fail; //指向自己的失败指针  
 55                     while(p!=NULL)  
 56                     {    
 57                         if(p->next[i]!=NULL)//失败指针有i孩子  
 58                         {   
 59                             temp->next[i]->fail=p->next[i]; //当前节点的i孩子的失败指针指向失败指针的i孩子,然后跳出  
 60                             break;   
 61                         }   
 62                         p=p->fail; //继续找失败指针  
 63                     }   
 64                     if(p==NULL) //若失败指针为空  
 65                         temp->next[i]->fail=root; //当前节点的i孩子的失败指针指向头  
 66                 }   
 67                 q[head++]=temp->next[i];  //进去的都是定义过失败指针的,故此过程是给其孩子定义失败指针  
 68             }   
 69         }     
 70     }   
 71 }   
 72 int query(node *root)  
 73 {   
 74     int i=0,cnt=0,index,len=strlen(str);   
 75     node *p=root;    
 76     while(str[i])  
 77     {    
 78         index=str[i]-'A';  //计算孩子的位置!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
 79         if(index<0||index>25)//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
 80         {  
 81             p=root;  
 82             i++;  
 83             continue;  
 84         }  
 85         while(p->next[index]==NULL && p!=root)   
 86             p=p->fail; //若没有i孩子节点,通过失败指针找与这之前相同的有i孩子的节点  
 87         p=p->next[index]; //指向其i孩子  
 88         p=(p==NULL)?root:p;   
 89         node *temp=p;   
 90         while(temp!=root && temp->count)  
 91         {   
 92             if(temp->count)//主要是改这里!!!!!!!!!!!!!!!!!!!!!!!!!!!  
 93             {  
 94                 cnt++;  
 95                 ++biaoshi[temp->count];  
 96             }  
 97             temp=temp->fail;   
 98         }   
 99         i++;                   
100     }      
101     return cnt;   
102 }   
103 int cmp(const void *a,const void *b)  
104 {  
105     int *c=(int*)a,*d=(int*)b;  
106     return *c-*d;  
107 }  
108 void print(int ji,int na,int n)  
109 {  
110   
111     printf("web %d:",na);  
112     for(int i=1;i<=n;++i)  
113     {  
114         if(biaoshi[i])  
115         {  
116         printf(" %d",i);  
117         }  
118     }  
119     printf("\n");  
120 }  
121 int main(){   
122     int n,t,i,j=0;   
123     while(scanf("%d",&n)!=EOF)  
124     {    
125         head=tail=0;   
126         node *root=new node();   
127         
128         getchar();   
129         for(i=1;i<=n;i++)  
130         {  
131             gets(keyword);   
132             strcpy(chuan[i],keyword);  
133             insert(keyword,root,i);   
134         }   
135         build_ac_automation(root);   
136         memset(biaoshi,0,sizeof(biaoshi));  
137         scanf("%s",str);  
138         query(root);  
139         for(i=1;i<=n;i++)  
140         {  
141             if(biaoshi[i])  
142             {  
143                 printf("%s: %d\n",chuan[i],biaoshi[i]);  
144             }  
145         }  
146         //printf("total: %d\n",j);  
147     }   
148     return 0;   
149 }  

 

posted on 2018-03-02 13:59  蔡军帅  阅读(171)  评论(0编辑  收藏  举报