正题
ybtoj AC自动机-5
题目大意
给出若干段01串,问你是否存在一个无限的01串,使得串中不存在给出的01串
解题思路
可以把给出01串用AC自动机处理,然后对每个01串的最后一位打上标记
根据AC自动机的连边性质(即若无该边,则连向next的该边),其实就是要找一个环,使得环上没有点被打上标记
找这个环可以用dfs实现
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 30010
using namespace std;
int n, w, ans, b[N], p[N], nx[N], to[N][2];
queue<int>d;
char s[N];
void insert(char* s)
{int n = strlen(s+1), now = 0;for (int i = 1; i <= n; ++i){int y = s[i] - '0';if (!to[now][y]) to[now][y] = ++w;now = to[now][y];}b[now] = 1;return;
}
void bfs()
{for (int i = 0 ; i < 2; ++i)if (to[0][i]) d.push(to[0][i]);while(!d.empty()){int h = d.front();d.pop();for (int i = 0; i < 2; ++i)if (!to[h][i]) to[h][i] = to[nx[h]][i];else{nx[to[h][i]] = to[nx[h]][i];b[to[h][i]] |= b[nx[to[h][i]]];//传递d.push(to[h][i]);}}return;
}
void dfs(int x)//搜索
{if (p[x])//到过,即找到了环{ans = 1;return;}p[x] = 1;if (!b[to[x][0]] && p[to[x][0]] >= 0) dfs(to[x][0]);if (ans) return;if (!b[to[x][1]] && p[to[x][1]] >= 0) dfs(to[x][1]);p[x] = -1;//记忆化return;
}
int main()
{scanf("%d", &n);for (int i = 1; i <= n; ++i){scanf("%s", s+1);insert(s);}bfs();dfs(0);if (ans) puts("TAK");else puts("NIE");return 0;
}