题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=2938
发现一个合法的串一定不会与病毒串匹配
如果让它无限长,就说明一直匹配不到病毒串
如果找到一个不经过病毒点的环,那么就存在无限长度的合法串
AC自动机建完图后,再用dfs判断即可
代码如下:
#include<cstring>
#include<ctype.h>
#include<cstdio>
#include<queue>
#define N 30050
using 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;
}