二進位制病毒審查委員會最近發現了如下的規律:某些確定的二進位制串是病毒的**。如果某段**中不存在任何一段病毒**,那麼我們就稱這段**是安全的。現在委員會已經找出了所有的病毒**段,試問,是否存在乙個無限長的安全的二進位制**。
示例:例如如果為病毒**段,那麼乙個可能的無限長安全**就是010101…。如果為病毒**段,那麼就不存在乙個無限長的安全**。
任務:請寫乙個程式:
1.在文字檔案wir.in中讀入病毒**;
2.判斷是否存在乙個無限長的安全**;
3.將結果輸出到檔案wir.out中。
輸入格式:
在文字檔案wir.in的第一行包括乙個整數n(n≤2000)(n\le 2000)(n≤2000),表示病毒**段的數目。以下的n行每一行都包括乙個非空的01字串——就是乙個病毒**段。所有病毒**段的總長度不超過30000。
輸出格式:
tak——假如存在這樣的**;
nie——如果不存在。
輸入樣例#1:301
1100000
輸出樣例#1:
nie題解:顯然我們是無法列舉乙個無限長的串的,那麼我們需要考慮找到這個構造方法.
既然是多模式串匹配,這裡我們考慮使用\(ac\)自動機.
首先還是先建出\(ac\)自動機,然後我們考慮如何才能找到乙個不被匹配的方法.我們知道如果匹配就是在\(ac\)自動機中訪問到乙個標記過的節點,或是該串的字首中含有單詞,所以我們可以在建樹的過程中將有單詞的點都打上標記,並且將它的所有子節點都打上標記,表示訪問到這些節點就不存在合法答案.
那麼如何找合法答案呢?因為在\(ac\)自動機上的匹配過程需要通過\(fail\)指標來跳轉,所以如果能找到乙個包含\(0\)節點(\(trie\)起始的空節點)的環,那麼就可以一直在這個環上跳轉一直不匹配成功,直接用\(dfs\)來找這個環就可以了.
#includeusing namespace std;
const int n = 3e4+5;
int n, cntn, ch[2][n], fail[n], chk[n], vis[n];
bool ok[n];
char s[n];
void insert(char *s)
ok[now] = 0;
}void build()
else ch[i][x] = ch[i][fail[x]];}}
}void dfs(int x)
int main()
題解 洛谷P2444 POI2000 病毒
給定n 2000 個01串,總長度不超過30000,問是否存在乙個無限長的01串不包含這n個串。這是一道ac自動機題目,需要對ac自動機 fail樹 trie圖有概念。將n個串建立ac自動機,標記每個字串的終結點以及它們在fail樹上的所有子節點為無效節點,問題就轉換成了trie圖上是否存在乙個從0...
洛谷 P2444 POI2000 病毒 解題報告
二進位制病毒審查委員會最近發現了如下的規律 某些確定的二進位制串是病毒的 如果某段 中不存在任何一段病毒 那麼我們就稱這段 是安全的。現在委員會已經找出了所有的病毒 段,試問,是否存在乙個無限長的安全的二進位制 示例 例如如果為病毒 段,那麼乙個可能的無限長安全 就是010101 如果為病毒 段,那...
洛谷P2444 病毒(AC自動機變形)
作為一道蹂躪了我一天的題 我也沒啥好說的了qaq 思路概述 我們知道,ac自動機是一種多模字串匹配演算法。構造 trie 樹 後,在模式串末尾一位的結點作上標記。平常的 ac自動機 是盡量能多接觸到這些標記,使總值最大。本題倒是有點奇葩,要構造乙個可行的無限長文字串,使沒有任何子串為給出模式串中的乙...