[POI2000]病毒,洛谷P2444,AC自动机

版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83894428

正题

       题面

       首先我们可以把这些病毒的AC自动机建出来。

       发现,如果有答案,那么这个答案在这个AC自动机上不管怎么跳都不会跳到一个病毒的结尾。

       那么我们就模拟跳的过程,如果成环了,输出TAK即可。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;

int n;
struct Trie{
	int son[2],t,fail;
}s[30010];
char ch[30010];
bool stack[30010],tf[30010];
int tot;
queue<int> f;

void insert(){
	int x=0,l=strlen(ch+1);
	for(int i=1;i<=l;i++){
		int temp=ch[i]-'0';
		if(s[x].son[temp]==-1){
			s[x].son[temp]=++tot;
			memset(s[tot].son,-1,sizeof(s[tot].son));
		}
		x=s[x].son[temp];
	}
	s[x].t=1;
}

void get_fail(){
	f.push(0);
	while(!f.empty()){
		int x=f.front();f.pop();
		for(int i=0;i<2;i++){
			int y=s[x].son[i];
			if(y==-1) continue;
			int op=s[x].fail;
			while(op!=0 && s[op].son[i]==-1) op=s[op].fail;
			if(x!=0 && s[op].son[i]!=-1) s[y].fail=s[op].son[i];
			s[y].t|=s[s[y].fail].t;
			f.push(y);
		}
	}
}

bool dfs(int x){
	stack[x]=tf[x]=true;
	for(int i=0;i<2;i++){
		int now=x;
		while(now!=0 && s[now].son[i]==-1) now=s[now].fail;
		int y=s[now].son[i];
		if(y==-1) y=0;
		if(stack[y]) return true;
		if(tf[y] || s[y].t) continue;
		if(dfs(y)) return true;
	}
	stack[x]=false;
	return false;
}

int main(){
	scanf("%d",&n);
	memset(s[0].son,-1,sizeof(s[0].son));
	for(int i=1;i<=n;i++) scanf("%s",ch+1),insert();
	get_fail();
	if(dfs(0)) printf("TAK");
	else printf("NIE");
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/83894428