HDU 3065 病毒侵袭持续中(AC自动机)
小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中推测。 题解:AC自动机模版题;
参考代码:
1 #include<cstring> 2 #include <cmath> 3 #include <iostream> 4 #include<queue> 5 #include<cstdio> 6 #include<map> 7 #include<string> 8 using namespace std; 9 const int SIGMA_SIZE = 128; 10 const int MAXNODE = 500005; 11 int n, m, X, Y; 12 char p[1010][51]; 13 14 struct ACautomata { 15 int ch[MAXNODE][SIGMA_SIZE]; 16 int f[MAXNODE]; 17 int val[MAXNODE]; 18 int last[MAXNODE]; 19 int cnt[2000]; 20 int sz; 21 int tot_web; 22 void init() 23 { 24 sz = 1; 25 memset(ch[0], 0, sizeof(ch[0])); 26 memset(val, 0, sizeof(val)); 27 memset(cnt, 0, sizeof(cnt)); 28 tot_web=0; 29 } 30 31 32 int idx(char c) { return (int)c; } 33 34 void insert(char *s,int v) 35 { 36 int now = 0,len=strlen(s); 37 for(int i = 0; i < len; i++) 38 { 39 int c = idx(s[i]); 40 if(!ch[now][c]) 41 { 42 memset(ch[sz], 0, sizeof(ch[sz])); 43 val[sz] = 0; 44 ch[now][c] = sz++; 45 } 46 now = ch[now][c]; 47 } 48 val[now] = v; 49 } 50 51 void print(int j) 52 { 53 if(j) 54 { 55 ++cnt[val[j]]; 56 print(last[j]); 57 } 58 } 59 60 void find(char *text) 61 { 62 int j = 0,len=strlen(text); 63 for(int i = 0; i < len; i++) 64 { 65 int c = idx(text[i]); 66 j = ch[j][c]; 67 if(val[j]) print(j); 68 else if(last[j]) print(last[j]); 69 } 70 } 71 72 void get_fail() 73 { 74 queue<int> q; f[0] = 0; 75 for (int c = 0; c < SIGMA_SIZE; c++) 76 { 77 int r = ch[0][c]; 78 if (r) 79 { 80 f[r]=0; 81 q.push(r); 82 last[r] = 0; 83 } 84 } 85 while (!q.empty()) 86 { 87 int u = q.front(); q.pop(); 88 for (int c = 0; c < SIGMA_SIZE; ++ c) 89 { 90 int r = ch[u][c]; 91 if (!r) 92 { 93 ch[u][c] = ch[f[u]][c]; 94 continue; 95 } 96 q.push(r); 97 int pre = f[u]; 98 while (pre && !ch[pre][c]) pre = f[pre]; 99 f[r] = ch[pre][c]; 100 last[r] = val[f[r]] ? f[r] : last[f[r]]; 101 } 102 } 103 } 104 105 } ac; 106 char text[2000010]; 107 int main() 108 { 109 110 while (~scanf("%d", &n)) 111 { 112 ac.init(); 113 for (int i = 1; i <= n; ++ i) 114 { 115 scanf("%s", p[i]); 116 ac.insert(p[i],i); 117 } 118 ac.get_fail(); 119 scanf("%s", text); 120 ac.find(text); 121 for (int i = 1;i <= n;++i) if(ac.cnt[i]) printf("%s: %d\n", p[i], ac.cnt[i]); 122 123 } 124 return 0; 125 }