hdu 3065 病毒侵袭持续中 AC自动机
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065
小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
Input
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
Output
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
题意描述:中文题,如上所述。
算法分析:AC自动机的简单题,大白书和很多博客都有AC自动机的详细介绍。AC自动机真心是个字符串处理的神奇东西,好好学习一下。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 #define PI 3.141592654 9 #define exp 1e-10 10 using namespace std; 11 const int maxn=1000+10; 12 const int M = 2000000+10; 13 14 struct node 15 { 16 node *fail; 17 node *child[26]; 18 int count; 19 int id; 20 node () { 21 fail=NULL; 22 count=0; 23 id=-1; 24 memset(child,NULL,sizeof(child)); 25 } 26 }*q[50000+100]; 27 int head,tail; 28 int n; 29 char keyword[maxn][55]; 30 int an[maxn]; 31 char str[M]; 32 33 void insert(node *root,char *str,int k) 34 { 35 node *p=root; 36 int len=strlen(str); 37 for (int i=0 ;i<len ;i++) 38 { 39 int index=str[i]-'A'; 40 if (p->child[index]==NULL) p->child[index]=new node(); 41 p=p->child[index]; 42 } 43 p->count++; 44 p->id=k;// no repeat 45 return ; 46 } 47 void build_AC(node *root) 48 { 49 root->fail=NULL; 50 q[head++]=root; 51 while (head != tail) 52 { 53 node *temp=q[tail++]; 54 node *p=NULL; 55 for (int i=0 ;i<26 ;i++) 56 { 57 if (temp->child[i]!=NULL) 58 { 59 if (temp==root) temp->child[i]->fail=root; 60 else 61 { 62 p=temp->fail; 63 while (p!=NULL) 64 { 65 if (p->child[i]!=NULL) 66 { 67 temp->child[i]->fail=p->child[i]; 68 break; 69 } 70 p=p->fail; 71 } 72 if (p==NULL) temp->child[i]->fail=root; 73 } 74 q[head++]=temp->child[i]; 75 } 76 } 77 } 78 return ; 79 } 80 void find(node *root,char *str) 81 { 82 int len=strlen(str); 83 node *p=root; 84 for (int i=0 ;i<len ;i++) 85 { 86 if (str[i]>='A' && str[i]<='Z') 87 { 88 int index=str[i]-'A'; 89 while (p->child[index]==NULL && p!=root) p=p->fail; 90 p=p->child[index]; 91 p= p==NULL ? root : p ; 92 node *temp=p; 93 while (temp!=root) 94 { 95 if (temp->count) an[temp->id ]++; 96 temp=temp->fail; 97 } 98 } 99 else p=root; 100 } 101 return ; 102 } 103 int main() 104 { 105 while (scanf("%d",&n)!=EOF) 106 { 107 head=tail=0; 108 memset(str,0,sizeof(str)); 109 memset(keyword,0,sizeof(keyword)); 110 memset(an,0,sizeof(an)); 111 node *root=new node(); 112 113 for (int i=0 ;i<n ;i++) 114 { 115 scanf("%s",keyword[i]); 116 insert(root,keyword[i],i); 117 } 118 build_AC(root); 119 getchar() ;gets(str) ; 120 find(root,str); 121 for (int i=0 ;i<n ;i++) 122 if (an[i]) printf("%s: %d\n",keyword[i],an[i]); 123 } 124 return 0; 125 }