【BZOJ2938】[POI2000]病毒
【BZOJ2938】[POI2000]病毒
题面
题解
现在看到字符串的题目就是$AC$自动机23333。。。(以前是哈希)
这题和普通的$AC$自动机题有些许不同
这题的文本串并未给出来
怎么办呢?
想一下,如果一个字符串匹配不到任何东西的话,会怎么样
是不是会一直在里面打转转?
所以就在$trie$图中找有没有没有环就行了
注意经过病毒串前缀的节点不可访问
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX_N = 3e4 + 5;
int c[MAX_N][2], fail[MAX_N], End[MAX_N], tot;
void insert(char *s) {
int o = 0;
for (int i = 0, l = strlen(s); i < l; i++) {
int son = s[i] - '0';
if (!c[o][son]) c[o][son] = ++tot;
o = c[o][son];
}
End[o] = 1;
}
void build() {
static queue<int> que;
for (int i = 0; i < 2; i++) if (c[0][i]) que.push(c[0][i]), fail[c[0][i]] = 0;
while (!que.empty()) {
int o = que.front(); que.pop();
for (int i = 0; i < 2; i++)
if (c[o][i]) fail[c[o][i]] = c[fail[o]][i], End[c[o][i]] |= End[fail[c[o][i]]], que.push(c[o][i]);
else c[o][i] = c[fail[o]][i];
}
}
bool ins[MAX_N], vis[MAX_N];
void dfs(int x) {
if (ins[x]) puts("TAK"), exit(0);
if (vis[x] || End[x]) return ;
vis[x] = ins[x] = 1;
dfs(c[x][0]);
dfs(c[x][1]);
ins[x] = 0;
}
int N; char s[MAX_N];
int main () {
scanf("%d", &N);
for (int i = 1; i <= N; i++) scanf("%s", s), insert(s);
build();
dfs(0);
puts("NIE");
return 0;
}