首先trie图建图,我们发现满足条件的方案就是在trie图跳的过程中不会找到标记过的字符串,就是有一个环就可以了。注意剪枝,
就是这个点搜过失败,就不再搜了。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int t[30005][27];
int fail[30005],num[30005],flag;
int sz,root,n,used[30005],no[30005];
char ss[30005];
void insert()
{
int l=strlen(ss),now=0;
for(int i=0;i<l;i++)
{
int ww=ss[i]-'0';
if(!t[now][ww])t[now][ww]=++sz;
now=t[now][ww];
}
num[now]++;
}
queue<int>M;
void getfail()
{
for(int i=0;i<=1;i++)if(t[0][i])M.push(t[0][i]);
while(!M.empty())
{
int now=M.front();M.pop();
for(int i=0;i<=1;i++)
{
if(t[now][i])
{
fail[t[now][i]]=t[fail[now]][i];
num[t[now][i]]+=num[fail[t[now][i]]];
M.push(t[now][i]);
}else
{
t[now][i]=t[fail[now]][i];
}
}
}
}
void dfs(int u,int fa)
{
if(no[u])return;
if(t[u][0]&&(!num[t[u][0]]))
{
if(used[t[u][0]])
{
flag=1;return;
}
used[t[u][0]]=1;
dfs(t[u][0],u);
used[t[u][0]]=0;
}
if(t[u][1]&&(!num[t[u][1]]))
{
if(used[t[u][1]])
{
flag=1;return;
}
used[t[u][1]]=1;
dfs(t[u][1],u);
used[t[u][1]]=0;
}
no[u]=1;
/* if(fail[u]&&(!num[fail[u]])&&(fail[u]!=fa))
{
// if(fail[u]==fa)
if(used[fail[u]])
{
flag=1;return;
}
used[fail[u]]=1;
dfs(fail[u],u);
used[fail[u]]=0;
}*/
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",ss);
insert();
}
getfail();//used[0]=1;
dfs(0,0);
if(flag)printf("TAK");
else printf("NIE");
return 0;
}