【洛谷P2444】病毒

题目

题目链接:https://www.luogu.com.cn/problem/P2444
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果 \(\{011, 11, 00000\}\) 为病毒代码段,那么一个可能的无限长安全代码就是 \(010101 \ldots\)。如果 \(\{01, 11, 000000\}\) 为病毒代码段,那么就不存在一个无限长的安全代码。
现在给出所有的病毒代码段,判断是否存在无限长的安全代码。
\(Q\leq 2000;\sum |S|\leq 3\times 10^4\)

思路

建出 AC 自动机,每一个点向它儿子连边。如果能在不走到中止节点的前提下形成环,那么存在无限长的代码,否则不存在。
注意如果一个点的 \(\text{fail}\) 是终止节点那么这个点也是中指节点。
时间复杂度 \(O(\sum |S|)\)

代码

#include <bits/stdc++.h>
using namespace std;

const int N=30010;
int n,m,tot,head[N],deg[N];
char s[N];

struct edge
{
	int next,to;
}e[N*2];

void add(int from,int to)
{
	e[++tot]=(edge){head[from],to};
	head[from]=tot; deg[to]++;
}

struct ACA
{
	int tot,ch[N][4],fail[N];
	bool end[N];
	
	void ins(char *s)
	{
		int len=strlen(s+1),p=0;
		for (int i=1;i<=len;i++)
		{
			int c=s[i]-48;
			if (!ch[p][c]) ch[p][c]=++tot;
			p=ch[p][c];
		}
		end[p]=1;
	}
	
	void build()
	{
		queue<int> q;
		if (ch[0][0]) q.push(ch[0][0]);
		if (ch[0][1]) q.push(ch[0][1]);
		ch[0][2]=ch[0][0]; ch[0][3]=ch[0][1];
		while (q.size())
		{
			int u=q.front(); q.pop();
			end[u]|=end[fail[u]];
			ch[u][2]=ch[u][0]; ch[u][3]=ch[u][1];
			if (!ch[u][2]) ch[u][2]=ch[fail[u]][2];
				else fail[ch[u][2]]=ch[fail[u]][2],q.push(ch[u][2]);
			if (!ch[u][3]) ch[u][3]=ch[fail[u]][3];
				else fail[ch[u][3]]=ch[fail[u]][3],q.push(ch[u][3]);
		}
	}
	
	void dfs(int x)
	{
		if (end[x]) return;
		if (ch[x][0]) dfs(ch[x][0]);
		if (ch[x][1]) dfs(ch[x][1]);
		add(x,ch[x][2]); add(x,ch[x][3]);
	}
}AC;

void topsort()
{
	queue<int> q;
	for (int i=0;i<=AC.tot;i++)
		if (!deg[i]) q.push(i),m++;
	while (q.size())
	{
		int u=q.front(); q.pop();
		for (int i=head[u];~i;i=e[i].next)
		{
			int v=e[i].to;
			deg[v]--;
			if (!deg[v]) q.push(v),m++;
		}
	}
}

int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		AC.ins(s);
	}
	AC.build(); AC.dfs(0);
	topsort();
	if (AC.tot+1==m) cout<<"NIE";
		else cout<<"TAK";
	return 0;
}
posted @ 2021-06-03 21:40  stoorz  阅读(125)  评论(0编辑  收藏  举报