bzoj 2938 病毒

首先trie圖建圖,我們發現滿足條件的方案就是在trie圖跳的過程中不會找到標記過的字符串,就是有一個環就可以了。注意剪枝,

就是這個點搜過失敗,就不再搜了。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int t[30005][27];
int fail[30005],num[30005],flag;
int sz,root,n,used[30005],no[30005];
char ss[30005];
void insert()
{
	int l=strlen(ss),now=0;
	for(int i=0;i<l;i++)
	{
		int ww=ss[i]-'0';
		if(!t[now][ww])t[now][ww]=++sz;
		now=t[now][ww];
	}
	num[now]++;
}
queue<int>M;
void getfail()
{
	for(int i=0;i<=1;i++)if(t[0][i])M.push(t[0][i]);
	while(!M.empty())
	{
		int now=M.front();M.pop();
		for(int i=0;i<=1;i++)
		{
			if(t[now][i])
			{
				fail[t[now][i]]=t[fail[now]][i];
				num[t[now][i]]+=num[fail[t[now][i]]];
				M.push(t[now][i]);
			}else
			{
				t[now][i]=t[fail[now]][i];
			}
		}
	}
}
void dfs(int u,int fa)
{
	if(no[u])return;
	if(t[u][0]&&(!num[t[u][0]]))
	{
		if(used[t[u][0]])
		{
			flag=1;return;
		}
		used[t[u][0]]=1;
		dfs(t[u][0],u);
		used[t[u][0]]=0;
	}
	if(t[u][1]&&(!num[t[u][1]]))
	{
		if(used[t[u][1]])
		{
			flag=1;return;
		}
		used[t[u][1]]=1;
		dfs(t[u][1],u);
		used[t[u][1]]=0;
	}
	no[u]=1;
/*	if(fail[u]&&(!num[fail[u]])&&(fail[u]!=fa))
	{
	//	if(fail[u]==fa)
		if(used[fail[u]])
		{
			flag=1;return;
		}
		used[fail[u]]=1;
		dfs(fail[u],u);
		used[fail[u]]=0;
	}*/
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",ss);
		insert();
	}
	getfail();//used[0]=1;
	dfs(0,0);
	if(flag)printf("TAK");
	else printf("NIE");
	return 0;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章