• 【洛谷P2444】病毒


    题目

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

    思路

    建出 AC 自动机,每一个点向它儿子连边。如果能在不走到中止节点的前提下形成环,那么存在无限长的代码,否则不存在。
    注意如果一个点的 ( ext{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;
    }
    
  • 相关阅读:
    closure
    运算符优先级
    css妙用
    BFC (块级格式化上下文)
    display:table-cell 详解
    line-height深入理解
    margin collapse
    探究 CSS 解析原理
    python入门
    spring与线程安全
  • 原文地址:https://www.cnblogs.com/stoorz/p/14847328.html
Copyright © 2020-2023  润新知