21.6.23 t3

tag:后缀树


建出后缀树,那么答案一定是叶节点。

dfs后缀树,每次走向的那条边的字符一定大于所有其他边的字符,就连一条边过去。

最后看一看有没有环。(传递闭包后自己大于自己)

复杂度 \(O(|S|^2n)\)\(S\) 为字符集,实际跑得挺快。


评测姬数据有问题,输入得用while(~scanf)

#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
    char ch; bool flag=false;
    while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
    for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
    if(flag)n=-n;
}

enum{
    MAXN = 100005
};

struct node{
    int son[12], fa, len, pos;
    #define son(x,opt) t[x].son[opt]
    #define fa(x) t[x].fa
    #define len(x) t[x].len
    #define pos(x) t[x].pos
}t[MAXN<<1];
int node_cnt, prv;

inline int insert(char v){
    int x = ++node_cnt; len(x) = len(prv)+1;
    while(prv and !son(prv,v)) son(prv,v) = x, prv = fa(prv);
    if(!prv) fa(x) = 1;
    else{
        int p = son(prv,v);
        if(len(p) == len(prv)+1) fa(x) = p;
        else{
            int new_p = ++node_cnt; len(new_p) = len(prv)+1;
            fa(new_p) = fa(p); fa(p) = fa(x) = new_p;
            copy(t[p].son,t[p].son+12,t[new_p].son);
            while(prv and son(prv,v)==p) son(prv,v) = new_p, prv = fa(prv);
        }
    }
    return prv=x;
}

vector<int>to[MAXN<<1];
char a[MAXN];
int pos[MAXN];
char able[MAXN<<1];

inline void clear(){
    for(int i=1; i<=node_cnt; i++) memset(t[i].son,0,sizeof t[i].son), fa(i) = len(i) = able[i] = 0, to[i].clear();
    node_cnt = prv = 1;
}

void pre_dfs(int x){for(int v:to[x]) pre_dfs(v), pos(x) = pos(v);}

int vis[12], tmpvis[12];
int cnt[12][12];

void dfs(int x){
    if(!to[x].size()){
        copy(vis,vis+12,tmpvis);
        for(int i=0; i<12; i++) for(int j=0; j<12; j++) if(tmpvis[j]>>i&1) tmpvis[j] or_eq tmpvis[i];
        for(int i=0; i<12; i++) if(tmpvis[i]>>i&1) return;
        return able[x]=true, void();
    }
    for(int v:to[x]){
        char vv = a[pos(v)+len(x)]-'a';
        for(int u:to[x]) if(v!=u){
            char vu = a[pos(u)+len(x)]-'a';
            vis[vv] |= 1<<vu; cnt[vv][vu]++;
        }
        dfs(v);
        for(int u:to[x]) if(v!=u){
            char vu = a[pos(u)+len(x)]-'a';
            cnt[vv][vu]--; if(!cnt[vv][vu]) vis[vv] ^= 1<<vu;
        }
    }
}

int main(){
    // freopen("3.in","r",stdin);
    int T; Read(T);
    while(~scanf("%s",a+1)){
        clear();
        int n = strlen(a+1);
        for(int i=n; i; i--) pos[i] = insert(a[i]-'a'), pos(pos[i]) = i;
        for(int i=1; i<=node_cnt; i++) if(fa(i)) to[fa(i)].push_back(i);
        pre_dfs(1); dfs(1);
        for(int i=1; i<=n; i++) putchar(able[pos[i]]^48);puts("");
    }
    return 0;
}
posted @ 2021-06-24 16:20  oisdoaiu  阅读(33)  评论(0编辑  收藏  举报