zoukankan      html  css  js  c++  java
  • [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;
    }
    
    
  • 相关阅读:
    形象理解ERP(转)
    禁用windows server 2008 域密码复杂性要求策略
    How to adding find,filter,remove filter on display method Form
    Windows Server 2008 R2激活工具
    How to using bat command running VS development SSRS report
    Creating Your First Mac AppGetting Started
    Creating Your First Mac AppAdding a Track Object 添加一个 Track 对象
    Creating Your First Mac AppImplementing Action Methods 实现动作方法
    Creating Your First Mac AppReviewing the Code 审查代码
    Creating Your First Mac AppConfiguring the window 设置窗口
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10181266.html
Copyright © 2011-2022 走看看