zoukankan      html  css  js  c++  java
  • BZOJ2938 [Poi2000]病毒

    BZOJ2938 [Poi2000]病毒

    洛谷传送

    Description

    - 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。
    如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。
    现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
    示例:例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。
    如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
    任务:请写一个程序:l 读入病毒代码;l 判断是否存在一个无限长的安全代码;l 将结果输出
    

    Input

    - 第一行包括一个整数n,表示病毒代码段的数目。
    以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。
    所有病毒代码段的总长度不超过30000。
    

    Output

    - 第一行输出一个单词:
    TAK——假如存在这样的代码;
    NIE——如果不存在。
    

    Sample Input 1

    - 3
    01 
    11 
    00000
    

    Sample Output 1

    - NIE
    

    Source

    - [Poi2000]
    

    思路

    • AC自动机模板题,将病毒串建AC自动机
    • 可以发现当AC自动机上满足如下条件时有无限长的安全代码输出 TAK
      • 不经过病毒串的结尾字符
      • 必须不经过病毒串的结尾字符所在的 (fail) 链上的所有字符
    • 否则输出 NIE

    code

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=2;
    const int Max=30010;
    int n;
    char s[Max];
    struct Trie
    {
    	int nx[Max][N],fail[Max];
    	bool vis[Max],end[Max],ins[Max];
    	int root,tot;
    	int newnode()
    	{
    		for(int i=0; i<N; i++)  nx[tot][i]=-1;
    		end[tot++]=false;
    		return tot-1;
    	}
    	void init(){    tot=0,root=newnode();   }
    	void insert(char s[])
    	{
    		int len=strlen(s),now=root,k;
    		for(int i=0; i<len; i++)
    		{
    			k=(int)(s[i]-'0');
    			if(nx[now][k]==-1)  nx[now][k]=newnode();
    			now=nx[now][k];
    		}
    		end[now]=true;
    	}
    	void build()
    	{
    		queue<int> Q;
    		fail[root]=root;
    		for(int i=0; i<N; i++)
    			if(nx[root][i]==-1) nx[root][i]=root;
    			else    fail[nx[root][i]]=root,Q.push(nx[root][i]);
    		int now;
    		while(!Q.empty())
    		{
    			now=Q.front();Q.pop();
    			for(int i=0; i<N; i++)
    				if(nx[now][i]==-1)  nx[now][i]=nx[fail[now]][i];
    				else
    				end[nx[now][i]]=end[nx[now][i]]|end[nx[fail[now]][i]],
    				//必须不经过病毒串的结尾字符所在的fail链上的所有字符
    				fail[nx[now][i]]=nx[fail[now]][i],
    				Q.push(nx[now][i]);
    		}
    	}
    	bool dfs(int t)
    	{
    		ins[t]=true;//标记访问路径 
    		for(int i=0; i<N; i++)
    		{
    			if(ins[nx[t][i]])	return true;
    			if(end[nx[t][i]]||vis[nx[t][i]])	continue;
    			vis[nx[t][i]]=true;//标记该条路径是否走过 
    			if(dfs(nx[t][i]))	return true;//继续访问 
    		}
    		ins[t]=false;
    		return 0;
    	}//判断是否有满足条件的环 
    	void pd()
    	{
    		if(dfs(0))	cout<<"TAK"<<endl;
    		else	cout<<"NIE"<<endl;
    	}
    }ac;
    
    int main()
    {
    	ac.init();
    	scanf("%d",&n);
    	for(int i=0; i<n; i++)
    		scanf("%s",s),ac.insert(s);
    	ac.build();
    	ac.pd();
    	return 0;
    }
    
  • 相关阅读:
    JavaScript 预解析
    JavaScript 作用域
    JavaScript 函数
    SlidesJS
    1. Skippr
    HTML5 模拟现实物理效果
    实现各种 CSS3 文本动画效果
    表单填写进度提示效果
    HTML5 WebGL 实现逼真的云朵效果
    【原创】bootstrap框架的学习 第八课 -[bootstrap表单]
  • 原文地址:https://www.cnblogs.com/vasairg/p/12818750.html
Copyright © 2011-2022 走看看