描述
传送门:我是传送门
小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
输入
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
输出
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
样例
输入
3
AA
BB
CC
ooxxCC%dAAAoen….END
输出
AA: 2
CC: 1
Note
题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。
计数策略也可一定程度上从Sample中推测。
思路
跟病毒侵袭实际上差不太多,也不知道我当时为什么写完病毒侵袭之后看了看这道题就放弃了。
一开始很奇怪的RE了无数次,也不知道哪里写搓了,正在要绝望的时候突然AC了···
代码
1 /* 2 * ============================================== 3 * 4 * Filename: C.cpp 5 * 6 * Link: http://acm.hdu.edu.cn/showproblem.php?pid=3065 7 * 8 * Version: 1.0 9 * Created: 2018/09/26 23时12分29秒 10 * Revision: none 11 * Compiler: g++ 12 * 13 * Author: 杜宁元 (https://duny31030.top/), duny31030@126.com 14 * Organization: QLU_浪在ACM 15 * 16 * ============================================== 17 */ 18 #include <bits/stdc++.h> 19 using namespace std; 20 #define clr(a, x) memset(a, x, sizeof(a)) 21 #define rep(i,a,n) for(int i=a;i<=n;i++) 22 #define pre(i,a,n) for(int i=n;i>=a;i--) 23 #define ll long long 24 #define max3(a,b,c) fmax(a,fmax(b,c)) 25 #define ios ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); 26 const double eps = 1e-6; 27 const int INF = 0x3f3f3f3f; 28 const int mod = 1e9 + 7; 29 const int N = 1005; 30 const int NN = 2001000; 31 char m[NN]; 32 char vir[N][55]; 33 int a[N]; 34 struct node 35 { 36 int son[27]; 37 int fail; 38 int count; 39 int number; 40 }ac[100*N]; 41 int tot = 0; 42 void init() 43 { 44 clr(a,0); 45 for(int i = 0;i < 50000;i++) 46 { 47 memset(ac[i].son,0,sizeof ac[i].son); 48 ac[i].count = 0; 49 ac[i].fail = 0; 50 ac[i].number = 0; 51 } 52 } 53 54 void Insert(char *s,int num) 55 { 56 int len = strlen(s); 57 int now = 0; 58 int tmp; 59 for(int i = 0;i < len;i++) 60 { 61 tmp = s[i]-'A'; 62 if(ac[now].son[tmp] == 0) 63 ac[now].son[tmp] = ++tot; 64 now = ac[now].son[tmp]; 65 } 66 ac[now].count++; 67 ac[now].number = num; 68 } 69 70 void Insert1(char *s,int id) 71 { 72 int len = strlen(s); 73 int now = 0; 74 int tmp; 75 for(int i = 0;i < len;i++) 76 { 77 tmp = s[i]-'A'; 78 if(ac[now].son[tmp] == 0) 79 ac[now].son[tmp] = ++tot; 80 now = ac[now].son[tmp]; 81 } 82 ac[now].count++; 83 ac[now].number = id; 84 } 85 86 void MakeFail() 87 { 88 queue<int> q; 89 for(int i = 0;i < 26;i++) 90 { 91 if(ac[0].son[i] != 0) 92 { 93 ac[ac[0].son[i]].fail = 0; 94 q.push(ac[0].son[i]); 95 } 96 } 97 while(!q.empty()) 98 { 99 int u = q.front(); 100 q.pop(); 101 for(int i = 0;i < 26;i++) 102 { 103 if(ac[u].son[i] != 0) 104 { 105 ac[ac[u].son[i]].fail = ac[ac[u].fail].son[i]; 106 q.push(ac[u].son[i]); 107 } 108 else 109 ac[u].son[i] = ac[ac[u].fail].son[i]; 110 } 111 } 112 } 113 114 void query(char *s) 115 { 116 int len = strlen(s); 117 int now = 0,tmp; 118 for(int i = 0;i < len;i++) 119 { 120 tmp = s[i]-'A'; 121 if(tmp < 0 || tmp > 25) 122 tmp = 26; 123 now = ac[now].son[tmp]; 124 for(int t = now;t && ac[t].count != -1;t = ac[t].fail) 125 { 126 if(ac[t].number > 0) 127 { 128 a[ac[t].number]++; 129 } 130 // ans += ac[t].count; 131 // ac[t].count = -1; 132 } 133 } 134 // return ans; 135 } 136 137 int main() 138 { 139 ios 140 #ifdef ONLINE_JUDGE 141 #else 142 freopen("in.txt","r",stdin); 143 // freopen("out.txt","w",stdout); 144 #endif 145 int n; 146 while(scanf("%d",&n) != EOF) 147 { 148 init(); 149 rep(i,1,n) 150 { 151 scanf("%s",vir[i]); 152 Insert1(vir[i],i); 153 } 154 ac[0].fail = 0; 155 MakeFail(); 156 scanf("%s",m); 157 query(m); 158 rep(i,1,n) 159 { 160 if(a[i]) 161 printf("%s: %d ",vir[i],a[i]); 162 } 163 } 164 fclose(stdin); 165 // fclose(stdout); 166 return 0; 167 }