BZOJ2938[Poi2000]病毒——AC自動機
阿新 • • 發佈:2018-06-08
訪問 超過 using uil while pan 文本文件 所有 build
你應在在文本文件WIN.OUT的第一行輸出一個單詞:
l TAK——假如存在這樣的代碼;
l NIE——如果不存在。
01
11
00000
AC自動機經典題,題目要求就是要在trie樹上在不走到危險節點的情況下,走出一個環。危險節點就是每個病毒字符串的終止節點,如果一個節點的失配標記指向危險節點,那它自己也是危險節點。在建立trie樹並找到每個節點的失配節點(但不要忘了標記危險節點)後只要dfs一下整棵trie樹,每走到一個點打上訪問標記,回溯到這個點再把標記刪除,如果走到了打標記的點就說明出現了環。
最後附上代碼。
題目描述
二進制病毒審查委員會最近發現了如下的規律:某些確定的二進制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那麽我們就稱這段代碼是安全的。現在委員會已經找出了所有的病毒代碼段,試問,是否存在一個無限長的安全的二進制代碼。 示例: 例如如果{011, 11, 00000}為病毒代碼段,那麽一個可能的無限長安全代碼就是010101…。如果{01, 11, 000000}為病毒代碼段,那麽就不存在一個無限長的安全代碼。 任務: 請寫一個程序: l 讀入病毒代碼; l 判斷是否存在一個無限長的安全代碼; l 將結果輸出輸入
第一行包括一個整數n,表示病毒代碼段的數目。以下的n行每一行都包括一個非空的01字符串——就是一個病毒代碼段。所有病毒代碼段的總長度不超過30000。輸出
樣例輸入
301
11
00000
樣例輸出
NIEAC自動機經典題,題目要求就是要在trie樹上在不走到危險節點的情況下,走出一個環。危險節點就是每個病毒字符串的終止節點,如果一個節點的失配標記指向危險節點,那它自己也是危險節點。在建立trie樹並找到每個節點的失配節點(但不要忘了標記危險節點)後只要dfs一下整棵trie樹,每走到一個點打上訪問標記,回溯到這個點再把標記刪除,如果走到了打標記的點就說明出現了環。
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 using namespace std; 9 struct tree 10 { 11 int fail; 12 int vis[3]; 13 bool end; 14 }a[30001]; 15 int cnt; 16 int n; 17 int num; 18 char s[30001]; 19 bool f[30001]; 20 bool v[30001]; 21 void build(char *s) 22 { 23 int l=strlen(s); 24 int now=0; 25 for(int i=0;i<l;i++) 26 { 27 int x=(s[i]-‘0‘); 28 if(a[now].vis[x]==0) 29 { 30 a[now].vis[x]=++cnt; 31 } 32 now=a[now].vis[x]; 33 } 34 a[now].end=true; 35 } 36 void bfs() 37 { 38 queue<int>q; 39 for(int i=0;i<2;i++) 40 { 41 if(a[0].vis[i]!=0) 42 { 43 a[a[0].vis[i]].fail=0; 44 q.push(a[0].vis[i]); 45 } 46 } 47 while(!q.empty()) 48 { 49 int now=q.front(); 50 q.pop(); 51 for(int i=0;i<2;i++) 52 { 53 if(a[now].vis[i]!=0) 54 { 55 a[a[now].vis[i]].fail=a[a[now].fail].vis[i]; 56 q.push(a[now].vis[i]); 57 if(a[a[a[now].fail].vis[i]].end) 58 { 59 a[a[now].vis[i]].end=true; 60 } 61 } 62 else 63 { 64 a[now].vis[i]=a[a[now].fail].vis[i]; 65 } 66 } 67 } 68 } 69 void dfs(int d) 70 { 71 v[d]=true; 72 for(int i=0;i<2;i++) 73 { 74 if(v[a[d].vis[i]]) 75 { 76 printf("TAK"); 77 exit(0); 78 } 79 else if(!a[a[d].vis[i]].end&&!f[a[d].vis[i]]) 80 { 81 f[a[d].vis[i]]=true; 82 dfs(a[d].vis[i]); 83 } 84 } 85 v[d]=false; 86 } 87 int main() 88 { 89 scanf("%d",&n); 90 for(int i=1;i<=n;i++) 91 { 92 scanf("%s",&s); 93 build(s); 94 } 95 a[0].fail=0; 96 bfs(); 97 dfs(0); 98 printf("NIE"); 99 return 0; 100 }
BZOJ2938[Poi2000]病毒——AC自動機