BZOJ2938:[POI2000] 病毒
生活随笔
收集整理的這篇文章主要介紹了
BZOJ2938:[POI2000] 病毒
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Description
二進(jìn)制病毒審查委員會(huì)最近發(fā)現(xiàn)了如下的規(guī)律:某些確定的二進(jìn)制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那么我們就稱這段代碼是安全的。現(xiàn)在委員會(huì)已經(jīng)找出了所有的病毒代碼段,試問,是否存在一個(gè)無限長的安全的二進(jìn)制代碼。 示例: 例如如果{011, 11, 00000}為病毒代碼段,那么一個(gè)可能的無限長安全代碼就是010101…。如果{01, 11, 000000}為病毒代碼段,那么就不存在一個(gè)無限長的安全代碼。 任務(wù): 請(qǐng)寫一個(gè)程序: l???????? 讀入病毒代碼; l???????? 判斷是否存在一個(gè)無限長的安全代碼; l???????? 將結(jié)果輸出Input
第一行包括一個(gè)整數(shù)n,表示病毒代碼段的數(shù)目。以下的n行每一行都包括一個(gè)非空的01字符串——就是一個(gè)病毒代碼段。所有病毒代碼段的總長度不超過30000。Output
你應(yīng)在在文本文件WIN.OUT的第一行輸出一個(gè)單詞: l???????? TAK——假如存在這樣的代碼; l???????? NIE——如果不存在。Sample Input
301
11
00000
Sample Output
NIE 思路: 首先將所有病毒串建一棵AC自動(dòng)機(jī)。 想象一個(gè)無限長的安全代碼存在,那么拿它到AC自動(dòng)機(jī)上匹配,它會(huì)一直匹配但是一直匹配不成功。 也就是說匹配的時(shí)候不能匹配到End為1的結(jié)點(diǎn)(設(shè)為x),且fail指針指向終點(diǎn)的點(diǎn)(設(shè)為y)也不能匹配到,因?yàn)閞oot..x是root..y的一個(gè)后綴。 而要無限長,即一直匹配,就說明在匹配過程中會(huì)遇上一個(gè)環(huán)。 所以就是在AC自動(dòng)機(jī)上看有沒有環(huán)就行了。感覺每做一道AC自動(dòng)機(jī)的題就重新學(xué)一遍AC自動(dòng)機(jī)
#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]]; //對(duì)于File指向End的點(diǎn)也不能訪問到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
總結(jié)
以上是生活随笔為你收集整理的BZOJ2938:[POI2000] 病毒的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django 框架入门篇(安装与创建项目
- 下一篇: 关于Scala递归返回参数的问题