BZOJ2938[Poi2000]病毒 AC自动机

来源:互联网 发布:查看linux防火墙状态 编辑:程序博客网 时间:2024/05/21 17:22

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=2938

发现一个合法的串一定不会与病毒串匹配
如果让它无限长,就说明一直匹配不到病毒串
如果找到一个不经过病毒点的环,那么就存在无限长度的合法串
AC自动机建完图后,再用dfs判断即可

代码如下:

#include<cstring>#include<ctype.h>#include<cstdio>#include<queue>#define N 30050using namespace std;inline int read(){    int x=0,f=1;char c;    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));    return x*f;}int n;char s[N];struct Node{    Node *ch[2],*nex;    bool b,vis,inq;    Node():nex(NULL){        b=vis=inq=false;        ch[0]=ch[1]=NULL;    }}*root=new Node;queue<Node*>q;inline void Insert(char *s){    Node *x=root;    int len=strlen(s+1);    for(int i=1;i<=len;i++){        if(!x->ch[s[i]-'0']) x->ch[s[i]-'0']=new Node;        x=x->ch[s[i]-'0'];    }    x->b=true;}inline void GetFail(){    root->nex=root;    for(int i=0;i<2;i++){        if(root->ch[i]) q.push(root->ch[i]),root->ch[i]->nex=root;        else root->ch[i]=root;    }    while(!q.empty()){        Node *x=q.front();q.pop();        for(int i=0;i<2;i++){            if(x->ch[i]) x->ch[i]->nex=x->nex->ch[i],q.push(x->ch[i]);            else x->ch[i]=x->nex->ch[i];        }        Node *tmp=x->nex;        while(tmp!=root && !tmp->b) tmp=tmp->nex;        if(tmp->b) x->b=true;    }}bool check(Node *x){    x->inq=true;    for(int i=0;i<2;i++){        if(x->ch[i]->inq) return true;        if(x->ch[i]->b || x->ch[i]->vis) continue;        x->ch[i]->vis=true;        if(check(x->ch[i])) return true;    }    x->inq=false;    return false;}int main(){    n=read();    for(int i=1;i<=n;i++){        scanf("%s",s+1);        Insert(s);    }    GetFail();    if(check(root)) puts("TAK");    else puts("NIE");return 0;}
原创粉丝点击