题目大意:给出n个病毒代码,判断是否有无限长度的代码满足:不包含任何病毒代码
题解:无限长就是能在Trie图上一直走,永远失配
单词结点x不能走,fail指向x的y也不能走,建出Trie图
形成一个有向图,从根节点dfs找环
我的收获:Trie图!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define idx s[i]-'0'
const int M=30010;
int n;
char s[M];
struct AC_DFA{
int tot,c[M][2],fail[M],q[M],l,r;bool dang[M],ins[M],bo[M];
void insert(){
int x=0,len=strlen(s);
for(int i=0;i<len;i++){
if(!c[x][idx]) c[x][idx]=++tot;
x=c[x][idx];
}
dang[x]=1;
}
void getfail(){
l=0,q[r=1]=0,fail[0]=-1;
while(l!=r){
int x=q[++l];
for(int i=0;i<=1;i++)
if(c[x][i]) q[++r]=c[x][i],fail[c[x][i]]=!x?0:c[fail[x]][i],dang[c[x][i]]|=dang[fail[c[x][i]]];
else c[x][i]=!x?0:c[fail[x]][i];
}
}
bool dfs(int x){
ins[x]=1;
for(int i=0;i<=1;i++){
int v=c[x][i];
if(ins[v]) return 1;
if(bo[v]||dang[v]) continue;
bo[v]=1;
if(dfs(v)) return 1;
}
ins[x]=0;return 0;
}
}T;
void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",s),T.insert();
T.getfail(),puts(T.dfs(0)?"TAK":"NIE");
}
int main()
{
init();
return 0;
}