我们建SAM,搞出parent树。
然后考虑哪些串是可能的识别子串,显然是那些|Right|=1的节点所代表的串。考虑这样的节点x,它的mn=mx[par[x]]+1,mx=mx[x],结尾字符为原串第r个。则他会对r-mn+1~r贡献一个mn的可能答案,对r-mx+1~r-mn贡献一个
-x+r+1的可能答案。于是两棵线段树分别维护一下最小值即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
int n=0,m,par[N<<1],son[N<<1][26],mx[N<<1],sz[N<<1],id[N<<1];
int a[N<<1],cnt[N],rt,lst;
char s[N];
struct node{
int tag1,tag2;
}tr[N<<2];
inline void ins(int ch,int xx){
int p=lst,np=++n;lst=np;mx[np]=mx[p]+1;sz[np]=1;id[np]=xx;
for(;p&&!son[p][ch];p=par[p]) son[p][ch]=np;
if(!p){par[np]=rt;return;}
int q=son[p][ch];
if(mx[q]==mx[p]+1){par[np]=q;return;}
int nq=++n;mx[nq]=mx[p]+1;memcpy(son[nq],son[q],sizeof(son[q]));
par[nq]=par[q];par[q]=par[np]=nq;
for(;p&&son[p][ch]==q;p=par[p]) son[p][ch]=nq;
}
inline void change(int p,int l,int r,int x,int y,int val){
if(x<=l&&r<=y){tr[p].tag1=min(tr[p].tag1,val);return;}
int mid=l+r>>1;
if(x<=mid) change(p<<1,l,mid,x,y,val);
if(y>mid) change(p<<1|1,mid+1,r,x,y,val);
}
inline void change2(int p,int l,int r,int x,int y,int val){
if(x<=l&&r<=y){tr[p].tag2=min(tr[p].tag2,val);return;}
int mid=l+r>>1;
if(x<=mid) change2(p<<1,l,mid,x,y,val);
if(y>mid) change2(p<<1|1,mid+1,r,x,y,val);
}
inline int ask(int p,int l,int r,int x){
if(l==r) return tr[p].tag1;
int mid=l+r>>1;
if(x<=mid) return min(ask(p<<1,l,mid,x),tr[p].tag1);
return min(ask(p<<1|1,mid+1,r,x),tr[p].tag1);
}
inline int ask2(int p,int l,int r,int x){
if(l==r) return tr[p].tag2;
int mid=l+r>>1;
if(x<=mid) return min(ask2(p<<1,l,mid,x),tr[p].tag2);
return min(ask2(p<<1|1,mid+1,r,x),tr[p].tag2);
}
inline void build(int p,int l,int r){
tr[p].tag1=tr[p].tag2=inf;
if(l==r) return;int mid=l+r>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
int main(){
// freopen("a.in","r",stdin);
scanf("%s",s+1);m=strlen(s+1);lst=rt=++n;
for(int i=1;i<=m;++i) ins(s[i]-'a',i);
for(int i=1;i<=n;++i) cnt[mx[i]]++;
for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
for(int i=n;i>=1;--i) a[cnt[mx[i]]--]=i;build(1,1,m);
for(int i=n;i>=1;--i){
int x=a[i];sz[par[x]]+=sz[x];if(sz[x]>1) continue;
int len=mx[par[x]]+1,r=id[x];
change(1,1,m,r-len+1,r,len);change2(1,1,m,r-mx[x]+1,r-len+1,r+1);
}for(int i=1;i<=m;++i){
int res=ask(1,1,m,i),res1=-i+ask2(1,1,m,i);
printf("%d\n",min(res,res1));
}
return 0;
}