Description

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
l         读入病毒代码;
l         判断是否存在一个无限长的安全代码;
l         将结果输出

Input

 
第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

Output

你应在在文本文件WIN.OUT的第一行输出一个单词:
l         TAK——假如存在这样的代码;
l         NIE——如果不存在。

Sample Input

3
01
11
00000

Sample Output

NIE

这明显是一道字符串匹配问题,那么就是AC自动机了
引用黄学长博客的一段话

如果一个串能无限长,也就是说它可以在AC自动机上一直进行匹配但就是匹配不上

也就是说匹配指针不能走到val为1的结点,设这个点为x

即root..x是一个病毒串

那么fail指针指向x的y也不能走

因为root..x是root..y的一个后缀

处理出来判断有向图是否有环

dfs即可


就是这样,代码:

#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<map>
#include<set>
using namespace std;


struct AC
{
int cnt;
int next[30010][2];
int fail[30010],d[30010],q[30010];
bool vis[30010],ins[30010];
char ch[30010];
__attribute__((__optimize__("-O2"))) inline AC()
{
for(int i = 0; i < 2; i ++)next[0][i]=1;
cnt = 1;
}
__attribute__((__optimize__("-O2"))) inline void insert()
{
scanf("%s",ch);
int now = 1;
int l = strlen(ch);
for(int i = 0; i < l; i ++)
{
if(!next[now][ch[i] - '0']) next[now][ch[i] - '0'] = ++ cnt;
now = next[now][ch[i] - '0'];
}
d[now] = 1;
}
__attribute__((__optimize__("-O2"))) inline void build()
{
int head = 0, tail = 1;
q[0] = 1;
fail[0] = 1;
while(head < tail)
{
int now = q[head];
head ++;
for(int i = 0; i < 2; i ++)
{
int v = next[now][i];
if(v == 0)
{
next[now][i] = next[fail[now]][i];
continue;
}
int k = fail[now];
while(!next[k][i]) k = fail[k];
fail[v] = next[k][i];
d[v] |= d[next[k][i]];
q[tail ++] = v;
}
}
}

__attribute__((__optimize__("-O2"))) bool dfs(int x)
{
ins[x] = 1;
for(int i = 0; i < 2; i ++)
{
int v = next[x][i];
if(ins[v]) return 1;
if(vis[v] || d[v]) continue;
vis[v] = 1;
if(dfs(v)) return 1;
}
ins[x] = 0;
return 0;
}
}ac;
int n;


int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i ++)
ac.insert();
ac.build();
if(ac.dfs(1)) printf("TAK");
else printf("NIE");

return 0;
}