二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
l 读入病毒代码;
l 判断是否存在一个无限长的安全代码;
l 将结果输出
第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。
你应在在文本文件WIN.OUT的第一行输出一个单词:
l TAK——假如存在这样的代码;
l NIE——如果不存在。
1 #include<cstdio>
2 #include<cstring>
3 const int maxn = 300006;
4 char ch[maxn];
5 int n;
6 int a[maxn][4],point[maxn],q[maxn],sz=1;
7 bool danger[maxn];
8 bool inq[maxn],vis[maxn];
9 void ins(){
10 int now=1,c;
11 int len=strlen(ch);
12 for(int i=0;i<len;i++){
13 c=ch[i]-‘0‘+1;
14 if(a[now][c])now=a[now][c];
15 else now=a[now][c]=++sz;
16 }
17 danger[now]=1;
18 }
19 void acm(){
20 for(int i=1;i<=2;i++)a[0][i]=1;
21 int l=0,r=0;
22 point[1]=0;q[r++]=1;
23 while(l<r){
24 int now=q[l++];
25 for(int i=1;i<=2;i++){
26 if(a[now][i]==0){
27 a[now][i] = a[point[now]][i];
28 continue;
29 }
30 int k=point[now];
31 while(!a[k][i])k=point[k];
32 point[a[now][i]]=a[k][i];
33 danger[a[now][i]]|=danger[a[k][i]];
34 q[r++]=a[now][i];
35 }
36 }
37 }
38 void dfs(int x){
39 printf("%d %d\n",x,point[x]);
40 for(int i=1;i<=2;i++){
41 if(a[x][i]){
42 dfs(a[x][i]);
43 }
44
45 }
46 }
47 bool check(int x){
48 inq[x]=1;
49 for(int i=1;i<=2;i++){
50 int to=a[x][i];
51 if(inq[to]==1)return 1;
52 if(danger[to]||vis[to])continue;
53 vis[to]=1;
54 if(check(to))return 1;
55 }
56 inq[x]=0;
57 return 0;
58 }
59 int main(){
60 scanf("%d",&n);
61 for(int i=1;i<=n;i++){
62 scanf("%s",ch);
63 ins();
64 }
65 acm();
66 check(1)?puts("TAK"):puts("NIE");
67 return 0;
68 }