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