洛谷2444 BZOJ2938 病毒 AC自動機

2021-08-22 05:04:44 字數 1251 閱讀 9668

題目鏈結

題意:給你n個01串,這些01串不能在你的串中出現,問你是否能構造出無限長的01串。

題解:

乍一看是挺不好想的。無限長會想到得到乙個可行的迴圈節,那些串不能出現卻不太好處理。我是聽別人講的這道題,所以我也沒有想好該怎麼說明才能想到ac自動機的,如果有能給出乙個合理的思維過程的朋友歡迎與我交流。

我們考慮ac自動機的原因是它可以用fail指標跳轉,如果在跳的過程中形成了環,那麼就可以構造無限長的01串了。我們在構造ac自動機時把每個限制不能出現的01串的最後乙個字元在trie樹上打上不能走的標記,然後根據ac自動機的性質,在處理fail指標的時候我們還要順便更新這個不能走的標記,也就是如果fail指標將要跳到的點有不能走的標記,那麼當前點也應該打上不能走的標記,原因是根據ac自動機的性質,從根到fail指標指向的那個點構成的01串一定是根到現在節點構成的01串的乙個字尾,也就是說當前01串的字尾已經是不合法的了,於是就要打上不能走的標記。然後我們用圖論的辦法找環,從trie樹的虛根0號點開始dfs,用類似tarjan的辦法,如果能往子節點走,就到子節點dfs,因為如果沒有子節點的話在處理fail的同時也處理了它不存在的子節點會跳到哪,這樣直到找到乙個到達點在當前棧裡的點,就找到了環。否則就是沒找到環。

**:

#include 

using

namespace

std;

int n,fail[30010],ch[30010][2],book[30010],cnt;

char s[30010];

queue

q;int vis[30010],in[30010];

inline

void build()

book[cur]=1;

}inline

void get_fail()

}while(!q.empty())

else

ch[x][i]=ch[fail[x]][i];}}

}inline

void dfs(int x)

if(vis[x]||book[x])

return;

in[x]=1;

vis[x]=1;

dfs(ch[x][0]);

dfs(ch[x][1]);

in[x]=0;

}int main()

get_fail();

dfs(0);

printf("nie\n");

return

0;}

洛谷P2444 POI2000 病毒

二進位制病毒審查委員會最近發現了如下的規律 某些確定的二進位制串是病毒的 如果某段 中不存在任何一段病毒 那麼我們就稱這段 是安全的。現在委員會已經找出了所有的病毒 段,試問,是否存在乙個無限長的安全的二進位制 示例 例如如果為病毒 段,那麼乙個可能的無限長安全 就是010101 如果為病毒 段,那...

題解 洛谷P2444 POI2000 病毒

給定n 2000 個01串,總長度不超過30000,問是否存在乙個無限長的01串不包含這n個串。這是一道ac自動機題目,需要對ac自動機 fail樹 trie圖有概念。將n個串建立ac自動機,標記每個字串的終結點以及它們在fail樹上的所有子節點為無效節點,問題就轉換成了trie圖上是否存在乙個從0...

洛谷 P2444 POI2000 病毒 解題報告

二進位制病毒審查委員會最近發現了如下的規律 某些確定的二進位制串是病毒的 如果某段 中不存在任何一段病毒 那麼我們就稱這段 是安全的。現在委員會已經找出了所有的病毒 段,試問,是否存在乙個無限長的安全的二進位制 示例 例如如果為病毒 段,那麼乙個可能的無限長安全 就是010101 如果為病毒 段,那...