LOJ10062(BZOJ2938)(Luogu2444)【POI 2000】

版权声明:发现蒟蒻ff_666,但转载请注明 https://blog.csdn.net/qq_42403731/article/details/82050993

LOJ10062

这题我们反向思考:
假如我们造出了一个无限串,在AC自动机上匹配,会发现什么?
显然,不会到达任意一个“有毒点”,所以会在有毒点之前借助nxt往回跳
然后既然是无限长,那么肯定会卡在某个环里
所以就可以从根开始 DFS找环就好了。。
PS:不要忘记构造AC自动机时“有毒点”的向下转移!
复杂度:玄学, O ( ) ,有了重复标记大概为 O ( | S | ) 。。

#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;
}

猜你喜欢

转载自blog.csdn.net/qq_42403731/article/details/82050993