「POI2000」病毒 - AC自动机 + DFS

Link: P2444 [POI2000]病毒

题面

题目描述

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

示例:

例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。

任务:

请写一个程序:

  1. 在文本文件WIR.IN中读入病毒代码;
  2. 判断是否存在一个无限长的安全代码;
  3. 将结果输出到文件WIR.OUT中。

输入格式

在文本文件WIR.IN的第一行包括一个整数n(n\le 2000)(n≤2000),表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

输出格式

在文本文件WIR.OUT的第一行输出一个单词:

TAK——假如存在这样的代码;

NIE——如果不存在。

输入输出样例

输入

1
2
3
4
3
01
11
00000

输出

1
NIE

题解

看到这种题先建个自动机, 考虑不包含给定串的文本串, 在Trie图上跑的时候必定无法到根节点(因为到根节点就代表有串与其像匹配), 于是在Trie图上找环就好了

十分窒息的地方在于我求trie图的时候写错变量名还有73pts....被卡了4次才过.....

代码:

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
#include <bits/stdc++.h>

const int CHAR_SET = 2;
const int MAXN = 30000 * CHAR_SET;

struct Node {
int ch[CHAR_SET << 1];
int fail, cnt;
int vis;
};

int tot;
Node t[MAXN + 10];

void insert (std::string S) {
int len = S.length(), rt = 0;
for (int i = 0; i < len; i++) {
int c = S[i] - '0';
if (!t[rt].ch[c]) t[rt].ch[c] = ++tot;
rt = t[rt].ch[c];
}
t[rt].cnt++;
t[rt].vis = 1;
}

void bfs () {
std::queue <int> q;
q.push(0);
while (!q.empty()) {
int now = q.front(); q.pop();
int k = t[now].fail;
for (int i = 0; i < CHAR_SET; i++) {
int to = t[now].ch[i];
if (!to) {
t[now].ch[i] = t[k].ch[i];
continue;
}
q.push(to);
t[to].fail = now ? t[k].ch[i] : 0;
t[to].vis |= now ? t[t[to].fail].vis : 0;
}
}
}

int vis[MAXN];
int dfv[MAXN];

bool dfs (int from) {
dfv[from] = 1;
for (int i = 0; i < CHAR_SET; i++) {
int to = t[from].ch[i];
if (dfv[to]) return 1;
if (vis[to] || t[to].vis) continue;
vis[to] = 1;
if (dfs(to)) return 1;
}
dfv[from] = 0;
return 0;
}

int n;
std::string str;

int main () {
std::cin >> n;
for (int i = 1; i <= n; i++) std::cin >> str, insert(str);
bfs();
return printf(dfs(0) ? "TAK\n" : "NIE\n") * 0;
}
坚持原创技术分享,您的支持将鼓励我继续创作!