题意:
给你n个病毒代码,问你是否存在一个无限长的安全代码, TAK——假如存在这样的代码;NIE——如果不存在。
题解:
用病毒串建好AC自动机,然后在上面跑dfs判断是否有环即可。
不加vis标记也对,但是会TLE
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 30050;
int nxt[MAXN][2],fail[MAXN],sta[MAXN],tot;
bool vis[MAXN],inque[MAXN],ok = false;
char s[MAXN];
inline void Insert(char *s){
int root=0,len=strlen(s);
for(int i=0;i<len;i++){
if(!nxt[root][s[i]-'0']) nxt[root][s[i]-'0']=++tot;
root=nxt[root][s[i]-'0'];
}
sta[root]=1;
}
inline void Build(){
queue<int> que;
for(int i=0;i<2;i++) if(nxt[0][i]) que.push(nxt[0][i]);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=0;i<2;i++){
if(nxt[u][i]){
fail[nxt[u][i]] = nxt[fail[u]][i];
sta[nxt[u][i]] |= sta[nxt[fail[u]][i]];
que.push(nxt[u][i]);
}else{
nxt[u][i] = nxt[fail[u]][i];
}
}
}
}
bool dfs(int u){
inque[u]=true;
for(int i=0;i<2;i++){
if(inque[nxt[u][i]]) return true;
if(vis[nxt[u][i]] || sta[nxt[u][i]]) continue;
vis[nxt[u][i]]=true;
if(dfs(nxt[u][i])) return true;
}
inque[u]=false;
return false;
}
int main(){
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",s),Insert(s);
Build();
if(dfs(0)) puts("TAK"); else puts("NIE");
return 0;
}