【POI2000】病毒

【POI2000】病毒

AC自動機

(注:POI  波蘭OI)

洛谷地址

在這裏插入圖片描述
在這裏插入圖片描述
先建立AC自動機,一般的題都是要儘可能地匹配,而這道題是儘可能不匹配。

就用DFS找一下有無從根出發不經過危險節點(末尾標上val的節點),的一個環即可。
貌似在getfail()時就已經把一些兒子連到了失敗指針的,具體的奧祕還不是很清楚。

注意:

  • 如果一個節點的失敗指針是危險節點,那麼這個點也是危險節點。
  • DFS時要記錄兩個數組,vis(是否在當前的環中,用完要清零),app(是否搜到過,不用清零),我們每次只搜索沒出現過的節點,若搜到已在環中就表示找到環了,推出程序即可。


推薦:
T^T
(╯▽╰)


#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5,N=3e4+5;
int n,siz=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;
	for(int i=0;i<=1;i++)
		if(ch[1][i]){
			fail[ch[1][i]]=1;
			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){
	vis[x]=app[x]=1;
	for(int i=0;i<=1;i++){
		if(vis[ch[x][i]]){
			printf("TAK");
			exit(0);
		}
		else if(!val[ch[x][i]]&&!app[ch[x][i]])dfs(ch[x][i]);
	}
	vis[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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章