• [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;
    }
    

      

  • 相关阅读:
    poj3468一个简单的整数问题,我昨天一下午才写好的水代码。
    【虚幻】虚幻引擎小技巧
    ubuntu添加并设置屏幕分辨率
    ECDH秘钥协商算法原理
    ECC椭圆曲线算法2
    Neighbor Discovery Protocol
    IPv6 linklocal 地址的功能和原理
    ECC椭圆曲线算法3
    Linux下使用可视化的串口调试工具cutecom
    AES五种加密模式(CBC、ECB、CTR、OCF、CFB)
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11272500.html
Copyright © 2020-2023  润新知