• [bzoj2938][Poi2000]病毒——AC自动机


    题目大意:

    给定n个01串,求是否存在一个长度无穷的01串使得这个01串不包含任何一个给定的串。

    思路:

    考虑AC自动机匹配的过程是在Trie树上不停地跳,那么如果我们可以找到一个串使得这个串可以一直在Trie上跳并且永远跳不到匹配节点就说明可行。
    可以发现这样的话这个串在AC自动机上的匹配一定是会出现环的,于是我们直接dfs找环就好了。
    考虑如何判断这个节点是否可以走到,即这个节点以及这个节点的所有fail都没有匹配才可以走,在求fail的时候可以预处理出来。
    dfs找环的时候记得要开两个bool数组,一个标记是否来过,一个标记是否在栈中。

    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define debug(x) cout<<#x<<"="<<x<<" "
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
    	freopen("bzoj2398.in","r",stdin);
    	freopen("bzoj2398.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
    	_=0; T f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    	for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
    	_*=f;
    }
    
    const int maxn=6e4+10;
    int n;
    int ans[maxn],tp;
    
    struct AC_Automaton{
    	int ch[maxn][2],num[maxn],fail[maxn],cnt;
    	bool vis[maxn],in[maxn];
    	void insert(char *s){
    		int len=strlen(s+1),u=0,c;
    		REP(i,1,len){
    			c=s[i]-'0';
    			if(!ch[u][c])ch[u][c]=++cnt;
    			u=ch[u][c];
    		}
    		++num[u];
    	}
    	void build(){
    		int h=1,t=0,q[maxn];
    		REP(i,0,1)if(ch[0][i])
    			q[++t]=ch[0][i];
    		while(h<=t){
    			int u=q[h++];
    			REP(i,0,1){
    				int v=ch[u][i];
    				if(v)q[++t]=v;
    				if(v){
    					fail[v]=ch[fail[u]][i];
    					num[v]|=num[fail[v]];
    				}
    				else ch[u][i]=ch[fail[u]][i];
    			}
    		}
    	}
    	bool dfs(int u){
    		if(num[u])return false;
    
    		if(in[u])return true;
    		if(vis[u])return false;
    
    		vis[u]=in[u]=1;
    		if(dfs(ch[u][0]) || dfs(ch[u][1]))return true;
    
    		in[u]=0;
    		return false;
    	}
    }T;
    
    int main(){
    	File();
    	char s[maxn];
    	read(n);
    	REP(i,1,n){
    		scanf("%s",s+1);
    		T.insert(s);
    	}
    
    	T.build();
    
    	printf("%s
    ",T.dfs(0) ? "TAK" : "NIE");
    
    	REP(i,1,tp)printf("%d",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    yii2中的url美化
    一级域名301重定向到www二级域名
    使用meta来控制浏览器的渲染方式
    同一页面不同编码的提交处理
    Yii2.0 UrlManager
    sqlsever连接两个不同服务器上的数据库进行查询
    php 实现传入参数的传出
    xcode如何修改项目名称
    ios如何实现应用之间的跳转
    ios程序如何实现系统自带的分享
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10181266.html
Copyright © 2020-2023  润新知