zoukankan      html  css  js  c++  java
  • [BZOJ2938][POI2000]病毒(AC自动机)

    Description

    二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

    示例: 例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。 任务: 请写一个程序: (1) 读入病毒代码;

    (2) 判断是否存在一个无限长的安全代码;

    (3) 将结果输出

    Input Format

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

    Output Format

    你应在在文本文件WIN.OUT的第一行输出一个单词: (1) TAK——假如存在这样的代码; (2) NIE——如果不存在。

    Solution

    建AC自动机,将fail指针合并到子节点上,然后形成一个有向图,

    然后在图上dfs,如果有环就是有无限长的串

    Code

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define N 30010
    using namespace std;
    
    char s[N];
    int n,T[N][2],fail[N],cnt=1,q[N];
    bool mark[N],vis[N],inq[N];
    
    inline void Insert(){
    	scanf("%s
    ",s);
    	int len=strlen(s),now=1;
    	for(int i=0;i<len;++i){
    		if(!T[now][s[i]-'0']) T[now][s[i]-'0']=++cnt;
    		now=T[now][s[i]-'0'];
    	}
    	mark[now]=1;
    }
    
    inline void getfail(){
    	int h=0,t=0,now;q[++t]=1;
    	for(int i=0;i<2;++i) T[0][i]=1;
    	while(h<t){
    		now=q[++h];
    		for(int i=0;i<2;++i)			
    			if(T[now][i]){
    				int k=fail[now];
    				while(!T[k][i]) k=fail[k];
    				fail[q[++t]=T[now][i]]=T[k][i];
    				mark[T[now][i]]|=mark[T[k][i]];
    			}else T[now][i]=T[fail[now]][i];	
    	}
    }
    
    bool dfs(int u){
    	inq[u]=1;
    	for(int i=0;i<2;++i){
    		int v=T[u][i];
    		if(inq[v]) return 1;
    		if(vis[v]||mark[v]) continue;
    		vis[v]=1;
    		if(dfs(v)) return 1;
    	}
    	inq[u]=0;
    	return 0;
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) Insert();
    	getfail();
    	dfs(1)?puts("TAK"):puts("NIE");
    	return 0;
    }
    
  • 相关阅读:
    CF446C [DZY loves Fibonacci]
    [BZOJ2286] 消耗战
    [CF Round #278] Tourists
    BZOJ2553 [BJWC2011]禁忌
    NOI2018D2T1 屠龙勇士
    BZOJ2333 棘手的操作
    bzoj4196: [Noi2015]软件包管理器(树链剖分)
    bzoj1833: [ZJOI2010]count 数字计数(数位DP)
    bzoj1026: [SCOI2009]windy数(数位DP)
    bzoj3631: [JLOI2014]松鼠的新家(树上差分)
  • 原文地址:https://www.cnblogs.com/void-f/p/9016508.html
Copyright © 2011-2022 走看看