zoukankan      html  css  js  c++  java
  • 题解 lg2444[POI2000]病毒 --AC自动机

    ac自动机练手好题:lg P2444 病毒

    题意

    (n)个模式串,问是否存在无限长的文本串其中不出现模式串

    思路

    构建这(n)个模式串AC自动机,满足要求的文本串必然满足在自动机上跑不会碰到结束节点,则必然会构成一个环.于是乎解法就是在Trie图上从根节点开始遍历,禁止遍历到结束节点,若找到环则输出(TAK),否则为(NIE)

    注意(自己掉的坑)

    1. trie图可以直接在trie树上建,新建图还麻烦了

    2. 如果这个点跳(fail)能跳到结束节点,其本身也应该被禁止

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int const N=3e5;
    int n;
    char s[N];
    bool ans;
    struct ACAutomaton{
    	int tot=0,_=0;
    	int fail[N],trie[N][2],ed[N],h[N];
    	bool ban[N],vis[N<<1],instack[N];
    	queue<int>q;
    	struct edge{
    		int to,next;
    	}e[N<<1];
    	void add(int be,int to){
    		e[++_].to=to,e[_].next=h[be],h[be]=_;
    	}
    	void init(){
    		memset(h,0,sizeof(h));
    		memset(trie,0,sizeof(trie));
    		memset(fail,0,sizeof(fail));
    		tot=0;
    	}
    	void insert(){
    		int len=strlen(s+1),now=0;
    		for(int i=1;i<=len;i++){
    			int x=s[i]-'0';
    			if(!trie[now][x]){trie[now][x]=++tot;}
    			now=trie[now][x];
    		}
    		ban[now]=1;
    	}
    	void getfail(){
    		for(int i=0;i<=1;i++){
    			if(trie[0][i]){
    				fail[trie[0][i]]=0;
    				add(trie[0][i],0);
    				q.push(trie[0][i]);
    			}
    		}
    		while(!q.empty()){
    			int x=q.front();q.pop();
    			for(int i=0;i<=1;i++){
    				add(trie[x][i],trie[fail[x]][i]);
    				if(trie[x][i]){
    					fail[trie[x][i]]=trie[fail[x]][i];
    					ban[trie[x][i]]|=ban[fail[trie[x][i]]];
    					q.push(trie[x][i]);
    				}else{
    					trie[x][i]=trie[fail[x]][i];
    				}
    			}
    		}
    	}
    	void dfs(int x){
    		//printf("%d
    ",x);
    		if(instack[x]){printf("TAK
    ");exit(0);}
    		if(vis[x]||ban[x])return;
    		vis[x]=1;instack[x]=1;
    		for(int i=0;i<2;i++){
    			dfs(trie[x][i]);
    		}
    		instack[x]=0;
    	}
    }ACA;
    int main(){
    	scanf("%d",&n);
    	ACA.init();
    	for(int i=1;i<=n;i++){
    		scanf("%s",s+1);
    		ACA.insert();
    	}
    	ACA.getfail();
    	ACA.dfs(0);
    	printf("NIE
    ");
    	return 0;
    }
    

  • 相关阅读:
    C#异步编程:多线程基础Thread类
    WPF:TextBox控件禁用中文输入
    C#:泛型的协变和逆变
    C#:泛型接口
    C#:泛型委托
    C#:泛型类
    Jetbrains Rider:缺少.NET Framework 4.5.2
    C#:泛型方法
    C#:泛型
    C#:接口
  • 原文地址:https://www.cnblogs.com/fpjo/p/13885018.html
Copyright © 2011-2022 走看看