版权声明:发现蒟蒻ff_666,但转载请注明 https://blog.csdn.net/qq_42403731/article/details/82050993
这题我们反向思考:
假如我们造出了一个无限串,在AC自动机上匹配,会发现什么?
显然,不会到达任意一个“有毒点”,所以会在有毒点之前借助nxt往回跳
然后既然是无限长,那么肯定会卡在某个环里
所以就可以从根开始 DFS找环就好了。。
PS:不要忘记构造AC自动机时“有毒点”的向下转移!
复杂度:玄学,
,有了重复标记大概为
。。
#include<bits/stdc++.h>
#define gt() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf;
const int maxs=(3e4)+5;
int n,que[maxs];bool vis[maxs],ins[maxs];
struct Trie{
int tot,c[maxs][3],nxt[maxs];bool f[maxs];
void insert(){
int rot=0;char ch=gt();while(!isdigit(ch)) ch=gt();
while(isdigit(ch)) ch-='0',rot=(c[rot][ch]?c[rot][ch]:c[rot][ch]=++tot),ch=gt();
f[rot]=1;
}
}AC;
void getnxt(){
int hed=0,tal=0,x;
if(AC.c[0][0]) que[++tal]=AC.c[0][0];if(AC.c[0][1]) que[++tal]=AC.c[0][1];
while(hed!=tal){
x=que[++hed];
if(AC.c[x][0]) AC.nxt[que[++tal]=AC.c[x][0]]=AC.c[AC.nxt[x]][0],AC.f[AC.c[x][0]]|=AC.f[AC.c[AC.nxt[x]][0]];else AC.c[x][0]=AC.c[AC.nxt[x]][0];
if(AC.c[x][1]) AC.nxt[que[++tal]=AC.c[x][1]]=AC.c[AC.nxt[x]][1],AC.f[AC.c[x][1]]|=AC.f[AC.c[AC.nxt[x]][1]];else AC.c[x][1]=AC.c[AC.nxt[x]][1];
}
}
void DFS(int x){
if(ins[x]) exit(puts("TAK")&0);
if(vis[x]||AC.f[x]) return;
ins[x]=vis[x]=1;
if(AC.c[x][0]) DFS(AC.c[x][0]);
if(AC.c[x][1]) DFS(AC.c[x][1]);
ins[x]=0;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) AC.insert();
getnxt();
DFS(0);
puts("NIE");
return 0;
}