题目大意:
给一些01串,询问有没有无限长的串其中不包括给定的串。
题目分析:
如果想要无限长的串,那它应该是一个循环的串。
只需要建一个AC自动机,然后在其中找到一个不包含单词节点的环就能顺着这个环找到一条无限长的01串且不包含给定串。
注意事项:
1、走过的节点要标记一下,不能再走一遍(会WA,还会TLE)。
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
#define N 32000
using namespace std;
int n;
char s[32000];
struct trie{
trie *son[2],*fail;
bool dc,ad;
trie()
{
son[0]=son[1]=fail=NULL;
dc=false;ad=false;
}
void inser(char *s)
{
trie *c=this;
for(int i=0;s[i];i++)
{
if(!c->son[s[i]-'0']) c->son[s[i]-'0']=new trie();
c=c->son[s[i]-'0'];
}
c->dc=true;
}
bool pc()
{
ad=true;
for(int i=0;i<2;i++)
{
if(son[i]->ad) return true;
if(son[i]->dc) continue;
son[i]->dc=true;
if(son[i]->pc()) return true;
}
ad=false;
return false;
}
}*V=new trie();
void Aho_Corasick_automaton(trie *V)
{
static trie *dl[N];
int l=1,r=0;
V->fail=V;
for(int i=0;i<2;i++)
{
if(!V->son[i]) V->son[i]=V;
else {V->son[i]->fail=V;dl[++r]=V->son[i];}
}
while(l<=r)
{
trie *c=dl[l++];
for(int i=0;i<2;i++)
{
if(!c->son[i]) c->son[i]=c->fail->son[i];
else {c->son[i]->fail=c->fail->son[i];dl[++r]=c->son[i];}
}
trie *t=c;
while(t!=V && !t->dc) t=t->fail;
if(t->dc) c->dc=true;
}
return;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
V->inser(s);
}
Aho_Corasick_automaton(V);
if(V->pc()) printf("TAK\n");
else printf("NIE\n");
return 0;
}