• [POI2000] 病毒


    题面

    一年多没写过trie 和 ac自动机真是有点吃力鸭。。。。

    我们先把trie建出来,顺便把AC自动机的边也都建好。

    首先,有一些点是不可以走的,不仅仅是叶子节点,还有到根的链构成的字符串有某个后缀正好和某个叶子到根的链构成的字符串相同的。

    这一步处理可以在AC自动机构建的时候顺带做好,考虑f[x]一直递归下去可以扫到x到根构成的链的字符串的所有后缀。

    然后再dfs就可以了,交叉边不用走(想一想为什么),再不走禁止的那些点,如果dfs到回边的话就返回true,恩然后就ok了;

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=33335;
    
    int c[N][2],f[N],n,num;
    bool v[N],ist[N];
    
    inline void ins(){
    	char ch=getchar();
    	while(ch!='0'&&ch!='1') ch=getchar();
    	
    	int now=0,p;
    	for(;ch=='0'||ch=='1';now=c[now][p],ch=getchar()){
    		p=ch-'0';
    		if(!c[now][p]) c[now][p]=++num;
    	}
    	
    	v[now]=1;
    }
    
    inline void get_fail(){
    	queue<int> q;
    	int x,r,u;
    	if(c[0][0]) q.push(c[0][0]);
    	if(c[0][1]) q.push(c[0][1]);
    	
    	while(!q.empty()){
    		x=q.front(),q.pop();
    		if(v[f[x]]) v[x]=1;
    		
    		for(int j=0;j<2;j++)
    			if(!c[x][j]) c[x][j]=c[f[x]][j];
    			else{
    				u=c[x][j],f[u]=c[f[x]][j];
    				q.push(u);
    			}
    	}
    }
    
    bool dfs(int x){
    	if(ist[x]) return 1;
    	if(v[x]) return 0;
    	
    //	cout<<x<<endl;
    	
    	v[x]=1,ist[x]=1;
    	
    	if(dfs(c[x][0])||dfs(c[x][1])) return 1;
    	
    	ist[x]=0;
    	return 0;
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) ins();
    	get_fail();
    	
    //	for(int i=0;i<=num;i++) printf("%d %d %d %d
    ",i,f[i],c[i][0],c[i][1]);
    	
    	if(dfs(0)) puts("TAK");
    	else puts("NIE");
    	return 0;
    }
    

      

  • 相关阅读:
    [导入]简单而强力的JS退弹代码(强制 弹出)
    [导入]在上传的图片上写字
    [导入]无法创建WEB项目文件路径与URL不符 处理方法
    [导入]ASCII码表完整版
    [导入]访QQ/MSN淡出窗口例子二则
    [导入]生成图片缩略图
    [导入]javascript调用webservice例子
    在字典的三级菜单中添加内容
    服务列表中找不到mysql
    CentOS 7安装后的配置
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11272500.html
Copyright © 2020-2023  润新知