1. 程式人生 > >[bzoj 2938] [Poi2000]病毒]

[bzoj 2938] [Poi2000]病毒]

span acm tdi i++ output time 發現 ger sca

傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=2938

[Poi2000]病毒

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 870 Solved: 447
[Submit][Status][Discuss]

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自動機匹配不到任意一個答案。

也就是這個圖形成了一個環。

我連有向圖判環都寫錯了

 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 }

[bzoj 2938] [Poi2000]病毒]