hdu--2896 病毒侵袭(ac自动机)
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
题意:中文题意不翻译
思路:用ac自动机去保存子串对主串进行查询,然后输出结果即可。
心路历程:这个题可以说浪费了我大多数的时间,主要原因是模板用的不对,百度得到的链表模板几乎都进行了测试,结果大多数都是MLE。直到去学习了数组类型的模板,才避免了这个问题。不过不得不承认数组类型的模板是非常好用的。
数组类型模板:
1 struct trie 2 { 3 int next[maxn][100],fail[maxn],end[maxn]; 4 int root,L; 5 int newnode() 6 { 7 for(int i=0;i<100;i++) 8 next[L][i]=-1; 9 end[L++]=-1; 10 return L-1; 11 } 12 void init() 13 { 14 L=0; 15 root=newnode(); 16 } 17 void insert(char buf[],int id) 18 { 19 int len=strlen(buf); 20 int now=root; 21 for(int i=0;i<len;i++) 22 { 23 if(next[now][buf[i]-' ']==-1) 24 next[now][buf[i]-' ']=newnode(); 25 now=next[now][buf[i]-' ']; 26 } 27 end[now]=id; 28 } 29 void build() 30 { 31 queue<int>Q; 32 fail[root]=root; 33 for(int i=0;i<100;i++) 34 if(next[root][i]==-1) 35 next[root][i]=root; 36 else 37 { 38 fail[next[root][i]]=root; 39 Q.push(next[root][i]); 40 } 41 while(!Q.empty()) 42 { 43 int now=Q.front(); 44 Q.pop(); 45 for(int i=0;i<100;i++) 46 if(next[now][i]==-1) 47 next[now][i]=next[fail[now]][i]; 48 else 49 { 50 fail[next[now][i]]=next[fail[now]][i]; 51 Q.push(next[now][i]); 52 } 53 } 54 } 55 int query(char buf[],int id) 56 { 57 int res[4]; 58 bool mark[510]={0}; 59 int len=strlen(buf); 60 int now=root; 61 memset(res,0,sizeof(res)); 62 for(int i=0;i<len;i++) 63 { 64 now=next[now][buf[i]-' ']; 65 int tmp=now; 66 while(tmp!=root) 67 { 68 if(end[tmp]!=-1) 69 { 70 if(!mark[end[tmp]]) 71 { 72 res[++res[0]]=end[tmp]; 73 mark[end[tmp]]=1; 74 } 75 } 76 tmp=fail[tmp]; 77 } 78 } 79 if(res[0]) 80 { 81 printf("web %d: ",id); 82 sort(res+1,res+res[0]+1); 83 for(int i=1;i<=res[0];i++) 84 { 85 printf("%d%c",res[i],i==res[0]?'\n':' '); 86 } 87 return 1; 88 } 89 return 0; 90 } 91 };
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <queue> 6 #include <algorithm> 7 using namespace std; 8 const int maxn=200*500+5; 9 struct trie 10 { 11 int next[maxn][100],fail[maxn],end[maxn]; 12 int root,L; 13 int newnode() 14 { 15 for(int i=0;i<100;i++) 16 next[L][i]=-1; 17 end[L++]=-1; 18 return L-1; 19 } 20 void init() 21 { 22 L=0; 23 root=newnode(); 24 } 25 void insert(char buf[],int id) 26 { 27 int len=strlen(buf); 28 int now=root; 29 for(int i=0;i<len;i++) 30 { 31 if(next[now][buf[i]-' ']==-1) 32 next[now][buf[i]-' ']=newnode(); 33 now=next[now][buf[i]-' ']; 34 } 35 end[now]=id; 36 } 37 void build() 38 { 39 queue<int>Q; 40 fail[root]=root; 41 for(int i=0;i<100;i++) 42 if(next[root][i]==-1) 43 next[root][i]=root; 44 else 45 { 46 fail[next[root][i]]=root; 47 Q.push(next[root][i]); 48 } 49 while(!Q.empty()) 50 { 51 int now=Q.front(); 52 Q.pop(); 53 for(int i=0;i<100;i++) 54 if(next[now][i]==-1) 55 next[now][i]=next[fail[now]][i]; 56 else 57 { 58 fail[next[now][i]]=next[fail[now]][i]; 59 Q.push(next[now][i]); 60 } 61 } 62 } 63 int query(char buf[],int id) 64 { 65 int res[4]; 66 bool mark[510]={0}; 67 int len=strlen(buf); 68 int now=root; 69 memset(res,0,sizeof(res)); 70 for(int i=0;i<len;i++) 71 { 72 now=next[now][buf[i]-' ']; 73 int tmp=now; 74 while(tmp!=root) 75 { 76 if(end[tmp]!=-1) 77 { 78 if(!mark[end[tmp]]) 79 { 80 res[++res[0]]=end[tmp]; 81 mark[end[tmp]]=1; 82 } 83 } 84 tmp=fail[tmp]; 85 } 86 } 87 if(res[0]) 88 { 89 printf("web %d: ",id); 90 sort(res+1,res+res[0]+1); 91 for(int i=1;i<=res[0];i++) 92 { 93 printf("%d%c",res[i],i==res[0]?'\n':' '); 94 } 95 return 1; 96 } 97 return 0; 98 } 99 }; 100 trie ac; 101 char buf[20005]; 102 int main() 103 { 104 int n,m; 105 while(~scanf("%d",&n)) 106 { 107 ac.init(); 108 for(int i=1;i<=n;i++) 109 { 110 scanf("%s",buf); 111 ac.insert(buf,i); 112 } 113 ac.build(); 114 scanf("%d",&m); 115 int total=0; 116 for(int i=1;i<=m;i++) 117 { 118 scanf("%s",buf); 119 total+=ac.query(buf,i); 120 } 121 printf("total: %d\n",total); 122 } 123 return 0; 124 }
真情推荐kuangbin大神的关于ac自动机的博客:http://www.cnblogs.com/kuangbin/category/402395.html