版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83894428
正题
首先我们可以把这些病毒的AC自动机建出来。
发现,如果有答案,那么这个答案在这个AC自动机上不管怎么跳都不会跳到一个病毒的结尾。
那么我们就模拟跳的过程,如果成环了,输出TAK即可。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
int n;
struct Trie{
int son[2],t,fail;
}s[30010];
char ch[30010];
bool stack[30010],tf[30010];
int tot;
queue<int> f;
void insert(){
int x=0,l=strlen(ch+1);
for(int i=1;i<=l;i++){
int temp=ch[i]-'0';
if(s[x].son[temp]==-1){
s[x].son[temp]=++tot;
memset(s[tot].son,-1,sizeof(s[tot].son));
}
x=s[x].son[temp];
}
s[x].t=1;
}
void get_fail(){
f.push(0);
while(!f.empty()){
int x=f.front();f.pop();
for(int i=0;i<2;i++){
int y=s[x].son[i];
if(y==-1) continue;
int op=s[x].fail;
while(op!=0 && s[op].son[i]==-1) op=s[op].fail;
if(x!=0 && s[op].son[i]!=-1) s[y].fail=s[op].son[i];
s[y].t|=s[s[y].fail].t;
f.push(y);
}
}
}
bool dfs(int x){
stack[x]=tf[x]=true;
for(int i=0;i<2;i++){
int now=x;
while(now!=0 && s[now].son[i]==-1) now=s[now].fail;
int y=s[now].son[i];
if(y==-1) y=0;
if(stack[y]) return true;
if(tf[y] || s[y].t) continue;
if(dfs(y)) return true;
}
stack[x]=false;
return false;
}
int main(){
scanf("%d",&n);
memset(s[0].son,-1,sizeof(s[0].son));
for(int i=1;i<=n;i++) scanf("%s",ch+1),insert();
get_fail();
if(dfs(0)) printf("TAK");
else printf("NIE");
}