P2444 [POI2000]病毒

描述

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

例如如果{011, 11, 00000}爲病毒代碼段,那麼一個可能的無限長安全代碼就是010101…。如果{01, 11, 000000}爲病毒代碼段,那麼就不存在一個無限長的安全代碼。

任務:

請寫一個程序:

  • 讀入病毒代碼;

  • 判斷是否存在一個無限長的安全代碼;

  • 將結果輸出

輸入

第一行包括一個整數n,表示病毒代碼段的數目。以下的n行每一行都包括一個非空的01字符串——就是一個病毒代碼段。所有病毒代碼段的總長度不超過30000。

輸出

你應在在文本文件WIN.OUT的第一行輸出一個單詞:

  • TAK——假如存在這樣的代碼;

  • NIE——如果不存在。

樣例輸入

3
01
11
00000

樣例輸出

NIE

網上找的:`

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5,N=3e4+5;
int n,siz=1/*1爲根節點*/,ch[N][2],val[N],fail[N];
char s[N];
void insert(){	
	int len=strlen(s+1);
	int p=1;
	for(int i=1;i<=len;i++){
		int c=s[i]-'0';
		if(!ch[p][c])ch[p][c]=++siz;
		p=ch[p][c];
	}
	val[p]++;
}
void getfail(){
	queue<int>q;
	fail[1]=0;//節點1的fail指針指向虛根0號節點 
	for(int i=0;i<=1;i++)
		if(ch[1][i]){//目標節點存在 
			fail[ch[1][i]]=1;//初始化起始節點的兒子的fail指針都指向起始節點 
			q.push(ch[1][i]);
		}
	while(!q.empty()){
		int c=q.front();q.pop();
		for(int i=0;i<=1;i++){
			int u=ch[c][i];	
			if(!u){
				ch[c][i]=ch[fail[c]][i];//與失配指針連邊 
				continue;
			}
			int v=fail[c];
			fail[u]=ch[v][i];
			if(val[ch[v][i]])val[u]=1;
			q.push(u);
		}
	}
}
int vis[N],app[N];
void dfs(int x){//從第x號節點開始深搜 
	vis[x]=app[x]=1;//vis[]爲1表示在環內,爲0表示不在環內;app表示訪問過,避免重複操作 
	for(int i=0;i<=1;i++){
		if(vis[ch[x][i]]){
			printf("TAK");
			exit(0);
		}
		else if(!val[ch[x][i]]/*ch[x][i]不是危險節點*/&&!app[ch[x][i]]/*未被訪問過*/)dfs(ch[x][i]);
	}
	vis[x]=0;//x不在下一次構成的環中,故需要標記爲0; 
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%s",s+1);
		insert();
	}
	getfail();//
	dfs(1);
	printf("NIE");
	return 0;
}

自己照貓畫虎:

#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
const int N=50000;
char st[N];
int n,trie[N][5],cnt=0,bo[N],que[N],fail[N],val[N],vis[N];
void insert(char *s){
	int u=0,len=strlen(s);
	for(int i=0;i<len;i++){
		int c=s[i]-'0';
		if(!trie[u][c]) trie[u][c]=++cnt;
		u=trie[u][c];
	}
	bo[u]++;
}
void bfs(){
	int u,q1=1,q2=0;
	for(int i=0;i<2;i++)
		if(trie[0][i]) que[++q2]=trie[0][i];
	for(q1,q2;q1<=q2;q1++){
		u=que[q1];
		for(int i=0;i<2;i++){
			int v=fail[u];
			if(trie[u][i]){
				que[++q2]=trie[u][i];
				fail[trie[u][i]]=trie[v][i];
				if(bo[trie[v][i]]) bo[trie[u][i]]++;
			}
			else
				trie[u][i]=trie[v][i];
		}
	}
} 
void dfs(int x){//從第x號節點開始深搜 
	val[x]=vis[x]=1;
	for(int i=0;i<2;i++){
		if(val[trie[x][i]]){
			printf("TAK\n");
			exit(0);
		}
		else if(!bo[trie[x][i]]&&!vis[trie[x][i]]) dfs(trie[x][i]);
	}
	val[x]=0;
}
int main()
{
	//freopen("WIN.OUT","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%s",st);
		insert(st);
	}
	bfs();
	dfs(1);
	printf("NIE\n");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章