BZOJ2938:[POI2000] 病毒
生活随笔
收集整理的這篇文章主要介紹了
BZOJ2938:[POI2000] 病毒
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Description
二進制病毒審查委員會最近發(fā)現(xiàn)了如下的規(guī)律:某些確定的二進制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那么我們就稱這段代碼是安全的。現(xiàn)在委員會已經(jīng)找出了所有的病毒代碼段,試問,是否存在一個無限長的安全的二進制代碼。 示例: 例如如果{011, 11, 00000}為病毒代碼段,那么一個可能的無限長安全代碼就是010101…。如果{01, 11, 000000}為病毒代碼段,那么就不存在一個無限長的安全代碼。 任務: 請寫一個程序: l???????? 讀入病毒代碼; l???????? 判斷是否存在一個無限長的安全代碼; l???????? 將結果輸出Input
第一行包括一個整數(shù)n,表示病毒代碼段的數(shù)目。以下的n行每一行都包括一個非空的01字符串——就是一個病毒代碼段。所有病毒代碼段的總長度不超過30000。Output
你應在在文本文件WIN.OUT的第一行輸出一個單詞: l???????? TAK——假如存在這樣的代碼; l???????? NIE——如果不存在。Sample Input
301
11
00000
Sample Output
NIE 思路: 首先將所有病毒串建一棵AC自動機。 想象一個無限長的安全代碼存在,那么拿它到AC自動機上匹配,它會一直匹配但是一直匹配不成功。 也就是說匹配的時候不能匹配到End為1的結點(設為x),且fail指針指向終點的點(設為y)也不能匹配到,因為root..x是root..y的一個后綴。 而要無限長,即一直匹配,就說明在匹配過程中會遇上一個環(huán)。 所以就是在AC自動機上看有沒有環(huán)就行了。感覺每做一道AC自動機的題就重新學一遍AC自動機
#include <bits/stdc++.h> #define ll long long using namespace std; const int p=10007; const int N=1e6+10; const int M=5e5+10; int n,T; char s[N]; struct acmach {int Next[M][2],Fail[M];bool End[M];bool vis[N],in[N];int root,L;int newnode(){for (int i=0;i<2;i++) Next[L][i]=-1;End[L]=0;return L++;}void init(){L=0;root=newnode();for (int i=0;i<N;i++) vis[i]=in[i]=0;}void Insert(char s[]){int len=strlen(s);int now=root;for (int i=0;i<len;i++){if (Next[now][s[i]-'0']==-1)Next[now][s[i]-'0']=newnode();now=Next[now][s[i]-'0'];}End[now]=1;}void build(){queue<int>q;Fail[root]=root; for (int i=0;i<2;i++)if (Next[root][i]==-1) Next[root][i]=root; else{Fail[Next[root][i]]=root;q.push(Next[root][i]);}while (!q.empty()){int now=q.front(); q.pop();End[now]|=End[Fail[now]]; //對于File指向End的點也不能訪問到for (int i=0;i<2;i++)if (Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i]; else{Fail[Next[now][i]]=Next[Fail[now]][i]; q.push(Next[now][i]);}}}bool dfs(int x){in[x]=1;for (int i=0;i<2;i++){int v=Next[x][i];if (in[v]) return 1;if (vis[v] || End[v]) continue;vis[v]=1;if (dfs(v)) return 1;}in[x]=0;return 0;} }ac; int main() {ac.init();scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%s",s);ac.Insert(s);}ac.build();if (ac.dfs(ac.root)) printf("TAK\n");else printf("NIE\n");return 0; } View Code轉(zhuǎn)載于:https://www.cnblogs.com/tetew/p/11545214.html
總結
以上是生活随笔為你收集整理的BZOJ2938:[POI2000] 病毒的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django 框架入门篇(安装与创建项目
- 下一篇: 关于Scala递归返回参数的问题