题解:对于一组病毒编码,我们构建AC自动机。如果存在一个无限长的安全代码,它在里面匹配,将一直匹配不上,也就是说,失配边会形成一个环。

所以构建好AC自动机后dfs失配边看有无环即可。

上代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 30005
 4 int n; char ch[N];
 5 struct acc
 6 {
 7     int f[N],next[N][2],cnt,head,tail,q[N];
 8     bool vis[N],ins[N],danger[N];
 9     acc(){
10         cnt=0;
11         memset(vis,0,sizeof(vis));
12         memset(ins,0,sizeof(ins));
13         memset(danger,0,sizeof(danger));
14     }
15     void inser(){
16         scanf("%s",ch); int p=0,len=strlen(ch);
17         for(int a,i=0;i<len;i++){
18             a=ch[i]-'0';
19             if(!next[p][a]) next[p][a]=++cnt;
20             p=next[p][a];
21         } danger[p]=1;
22     }
23     void getfail(){
24         head=0; tail=0;
25         for(int i=0;i<2;i++) if(next[0][i]) q[tail++]=next[0][i],f[next[0][i]]=0;
26         //一定不要直接把0丢进队列BFS,要分别把每个单独拿出来,不然是错的 
27         while(head<tail){
28             int p=q[head++];
29             for(int i=0;i<2;i++){
30                 int v=next[p][i];
31                 if(!v) {next[p][i]=next[f[p]][i]; continue;}
32                 int k=f[p];
33                 while(k && !next[k][i]) k=f[k]; k=next[k][i];
34                 f[v]=k;
35                  danger[v]|=danger[k];
36                 q[tail++]=v;
37             }
38         }
39     }
40     bool dfs(int x){
41         ins[x]=1;
42         for(int i=0;i<2;i++){
43             int v=next[x][i];
44             if(ins[v]) return 1;
45             if(vis[v] || danger[v]) continue;
46             vis[v]=1;
47             if(dfs(v)) return 1;
48         }
49         ins[x]=0;
50         return 0;
51     }
52 }acm;
53 int main(){
54     scanf("%d",&n);
55     for(int i=1;i<=n;i++) acm.inser();
56     acm.getfail();
57     if(acm.dfs(0)) puts("TAK");
58     else puts("NIE");
59     return 0;
60 }