「HDU-3065」病毒侵袭持续中-AC自动机

小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?

链接

HDU-3065

题解

直接跑 AC 自动机就好了,只需要判一下不用输出的。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <iostream>
#include <bitset>
#include <queue>
#include <climits>
const int MAXN = 1000 + 10;
struct Node {
int id, cnt;
Node *next[28], *fail;
Node() { id = -1, cnt = 0, fail = 0, memset(next, 0, sizeof(next)); }
} *root;
inline void insert(const char *s, int id) {
register int len = strlen(s);
Node *p = root;
for (register int i = 0; i < len; i++) {
if (!p->next[s[i] - 'A']) p->next[s[i] - 'A'] = new Node();
p = p->next[s[i] - 'A'];
}
p->cnt++, p->id = id;
}
inline void build() {
Node *p, *next;
std::queue<Node *> q;
q.push(root);
while (!q.empty()) {
p = q.front(), q.pop();
for (register int i = 0; i < 28; ++i) {
if (p->next[i]) {
next = p->fail;
while (next && !next->next[i]) next = next->fail;
p->next[i]->fail = (next ? next->next[i] : root), q.push(p->next[i]);
}
}
}
}
inline void clear(Node *p) {
for (register int i = 0; i < 26; ++i) if (p->next[i]) clear(p->next[i]);
delete p;
}
char s[MAXN][55], T[2000005];
int cnt[MAXN];
inline void query(const char *s) {
register int index, len = strlen(s);
Node *p = root;
for (register int i = 0; i < len; i++) {
if (isupper(s[i])) index = s[i] - 'A';
else index = 27;
while (!p->next[index] && p != root) p = p->fail;
p = p->next[index];
if (!p) p = root;
Node *tmp = p;
while (tmp != root && (~tmp->id)) ::cnt[tmp->id]++, tmp = tmp->fail;
}
}

int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0);
int n;
while (std::cin >> n) {
root = new Node();
memset(cnt, 0, sizeof(cnt));
for (register int i = 0; i < n; i++) std::cin >> s[i], insert(s[i], i);
build(), std::cin >> T, query(T);
for (register int i = 0; i < n; i++) {
if (cnt[i]) std::cout << s[i] << ": " << cnt[i] << "\n";
}
clear(root);
}
return 0;
}
#

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×