思路:先构建出一个ac自动机,将他优化成tire图,标记含有病毒代码的点P的flag=1,bfs这个图,从根节点开始,标记过的点不走,如果最后形成自环,则可以安全代码,否则bfs结束,没有安全代码;
涉及算法(bfs+ac自动机+tire图优化);
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2e3 + 10, M = 3e4 + 10;
int ne[M] = { 0 }, son[M][2], idx = 1, vis[M], flag[M], que[M];
bool st[M] = { 0 };
char s[N][M];
inline void insert(char str[]) {
int p = 1, len = strlen(str + 1);
for (int i = 1; i <= len; i++) {
int u = str[i] - '0';
if (!son[p][u])
son[p][u] = ++idx;
p = son[p][u];
}
st[p] = 1;
}
inline void build() {
for (int i = 0; i < 2; i++) son[0][i] = 1;
ne[1] = 0, que[1] = 1;
for (int q1 = 1, q2 = 1; q1 <= q2; q1++) {
int u = que[q1];
for (int i = 0; i < 2; i++) {
int v = ne[u], w = son[u][i];
while (!son[v][i]) v = ne[v];
v = son[v][i];
if (w) {
ne[w] = v, st[w] |= st[v];
que[++q2] = w;
} else {
son[u][i] = v;
}
}
}
}
inline void dfs(int u) {
vis[u] = flag[u] = 1;
for (int i = 0, v; i < 2; i++) {
v = son[u][i];
if (vis[v]) {
cout << "TAK" << endl;
exit(0);
} else if (!st[v] && !flag[v])
dfs(v);
}
vis[u] = 0;
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1);
insert(s[i]);
}
build();
dfs(1);
cout << "NIE" << endl;
return 0;
}
如有不解,可以私信