hdu 2896(AC自动机)
病毒侵袭
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 36709 Accepted Submission(s): 8149
Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
Input
第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
Sample Input
3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
Sample Output
web 1: 1 2 3
total: 1
1 /** 2 完成时间:2018.9.12 3 依言 4 算法:AC自动机 5 */ 6 #include<iostream> 7 #include<queue> 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 using namespace std; 12 const int SON=128; 13 const int MAXN=200*500+50; 14 15 struct AC_Auto 16 { 17 int root,L; 18 int next[MAXN][SON]; 19 int fail[MAXN]; 20 int num[4]; 21 int number[MAXN]; 22 int New_Node() 23 { 24 for(int i=0;i < SON;++i) 25 next[L][i]=-1; 26 num[L]=0; 27 return L++; 28 } 29 void Initial() 30 { 31 L=0; 32 root=New_Node(); 33 } 34 void Build_Trie(const char *s,const int id) 35 { 36 int now=root; 37 while(*s != '\0') 38 { 39 int index=*s; 40 if(next[now][index] == -1) 41 next[now][index]=New_Node(); 42 now=next[now][index]; 43 s++; 44 } 45 num[now]=id;//将结束字符赋值为病毒编号 46 } 47 void Build_Fail() 48 { 49 queue<int >myqueue; 50 for(int i=0;i < SON;++i) 51 if(next[root][i] == -1) 52 next[root][i]=root; 53 else 54 { 55 fail[next[root][i]]=root; 56 myqueue.push(next[root][i]); 57 } 58 while(!myqueue.empty()) 59 { 60 int now=myqueue.front(); 61 myqueue.pop(); 62 for(int i=0;i < SON;++i) 63 if(next[now][i] == -1) 64 next[now][i]=next[fail[now]][i]; 65 else 66 { 67 fail[next[now][i]]=next[fail[now]][i]; 68 myqueue.push(next[now][i]); 69 } 70 } 71 } 72 int Query(const char *s) 73 { 74 int cnt=0; 75 int now=root; 76 bool vis[MAXN]; 77 memset(vis,false,sizeof(vis)); 78 while(*s != '\0') 79 { 80 int index=*s; 81 now=next[now][index]; 82 int temp=now; 83 while(temp != root && num[temp] != 0 && !vis[num[temp]]) 84 { 85 number[cnt++]=num[temp]; 86 temp=fail[temp]; 87 vis[num[temp]]=true; 88 } 89 s++; 90 } 91 return cnt; 92 } 93 }; 94 AC_Auto ac; 95 char buf[10010]; 96 97 int main() 98 { 99 int N; 100 scanf("%d",&N); 101 ac.Initial(); 102 for(int i=1;i <= N;++i) 103 { 104 scanf("%s",buf); 105 ac.Build_Trie(buf,i); 106 } 107 ac.Build_Fail(); 108 int M; 109 scanf("%d",&M); 110 int total=0; 111 for(int i=1;i <= M;++i) 112 { 113 scanf("%s",buf); 114 int cnt=ac.Query(buf); 115 if(cnt > 0) 116 { 117 total++; 118 sort(ac.number,ac.number+cnt); 119 printf("web %d:",i); 120 for(int i=0;i < cnt;++i) 121 printf(" %d",ac.number[i]); 122 printf("\n"); 123 } 124 } 125 printf("total: %d\n",total); 126 127 return 0; 128 }