明显,这是让我们在trie图上找一个环。
暴力搜索就可以了。
不过我们还需要注意一个坑点
如果我们当前的后缀是一个病毒的结尾,所以我们要在处理失配指针时还要处理他的后缀是病毒片段。
我觉得这也算是一个写Ac自动机一类题的要注意的坑点吧。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
int n;
char data[30100];
int t[30100][2],tail;
int end[60200];
int fail[60200];
void ins()
{
int now=0,len=strlen(data)-1;
for(int i=0;i<=len;i++)
{
int nxt=data[i]-'0';
if(!t[now][nxt]) t[now][nxt]=++tail;
now=t[now][nxt];
}
end[now]+=1;
return ;
}
queue<int>q;
void make_fail()
{
if(t[0][0]) q.push(t[0][0]);
if(t[0][1]) q.push(t[0][1]);//直接展开得了
while(!q.empty())
{
int now=q.front();
q.pop();
if(t[now][0])
{
fail[t[now][0]]=t[fail[now]][0],q.push(t[now][0]);
if(end[t[fail[now]][0]]) end[t[now][0]]+=1;//处理病毒是否是其后缀
}
else t[now][0]=t[fail[now]][0];
if(t[now][1])
{
fail[t[now][1]]=t[fail[now]][1],q.push(t[now][1]);
if(end[t[fail[now]][1]]) end[t[now][1]]+=1;
}
else t[now][1]=t[fail[now]][1];
}
return ;
}
bool vis[60200];
void dfs(int now)
{
if(end[fail[now]]) return ;
if(vis[now])
{
printf("TAK");
exit(0);
}
vis[now]=true;
if(!end[t[now][0]]) dfs(t[now][0]);
if(!end[t[now][1]]) dfs(t[now][1]);
vis[now]=false;
return ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",data);
ins();
}
make_fail();
dfs(0);
printf("NIE");
return 0;
}