传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2938
思路:构建AC自动机,无限长的安全代码就是能一直在AC自动机上匹配而匹配不上任何一个危险串。依旧是匹配指针不能走到危险串的结尾点x,fail指针指向x的y也不能走,因为根据fail的定义,x这个危险串是y的后缀。找出危险节点后就是找环了,有环就有无限长的安全代码,否则没有。
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn=30010;
using namespace std;
int n;char s[maxn];
struct AC_DFA{
int tot,ch[maxn][2],fail[maxn],q[maxn],head,tail;bool dang[maxn],bo[maxn],ins[maxn];
void insert(){
int p=0;
for (int i=0;i<(int)strlen(s);p=ch[p][s[i]-'0'],i++) if (!ch[p][s[i]-'0']) ch[p][s[i]-'0']=++tot;
dang[p]=1;
}
void getfail(){
head=0,q[tail=1]=0,fail[0]=-1;
while (head!=tail){
int x=q[++head];
for (int i=0;i<=1;i++)
if (ch[x][i])
q[++tail]=ch[x][i],fail[ch[x][i]]=x==0?0:ch[fail[x]][i],dang[ch[x][i]]|=dang[fail[ch[x][i]]];
else ch[x][i]=x==0?0:ch[fail[x]][i];
}
}
bool dfs(int x){
ins[x]=1;
for (int i=0;i<=1;i++){
int v=ch[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;
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%s",s),T.insert();
T.getfail(),puts(T.dfs(0)?"TAK":"NIE");
return 0;
}