$SAM$是啥?来一发朴素的$SA$解法。
先把$SA$建出来。如果某两个子串$S_1,S_2$相同的话,它们所属的后缀的$LCP$要大于等于$len(S_1)$。
$LCP$是$\min\{height[k]\}(i<k\le j)$,然后就变成了对每个长度$L$,求出最长的一段区间$[l,r]$使$height[i]\ge L(i\in[l,r])$。单调栈扫两遍就行了。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 250005
#define inf 0x3f3f3f3f
#define pn putchar('\n')
#define px(x) putchar(x)
#define ps putchar(' ')
#define pd puts("======================")
#define pj puts("++++++++++++++++++++++")
using namespace std;
inline int read(){
int x=0,y=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return y?-x:x;
}
int sa[maxn],rk[maxn],hei[maxn],tp[maxn],tax[maxn],ll[maxn],rr[maxn],ans[maxn],n,m;
char s[maxn];
struct MonoStack{
int sta[maxn],top;
inline void push(int x){
while(top>1&&hei[sta[top]]>=hei[x])--top;
sta[++top]=x;
}
inline int back(){
return sta[top-1];
}
inline void clear(){
top=0;
}
}st;//单调栈
void Rsort(){
for(register int i=0;i<=m;++i)tax[i]=0;
for(register int i=1;i<=n;++i)++tax[rk[i]];
for(register int i=1;i<=m;++i)tax[i]+=tax[i-1];
for(register int i=n;i;--i)sa[tax[rk[tp[i]]]--]=tp[i];
}
void Ssort(){
for(register int i=1;i<=n;++i)rk[i]=s[i],tp[i]=i;
m=225,Rsort();
for(register int k=1,p=0;p<n;m=p,k<<=1){
p=0;
for(register int i=1;i<=k;++i)tp[++p]=n-k+i;
for(register int i=1;i<=n;++i)if(sa[i]>k)tp[++p]=sa[i]-k;
Rsort();
for(register int i=1;i<=n;++i)tp[i]=rk[i];
rk[sa[1]]=p=1;
for(register int i=2;i<=n;++i)
rk[sa[i]]=tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+k]==tp[sa[i-1]+k]?p:++p;
}
}
void get_height(){
int k=0,x;
for(register int i=1;i<=n;++i){
if(rk[i]==1)continue;
if(k)--k;
x=sa[rk[i]-1];
while(i+k<=n&&x+k<=n&&s[i+k]==s[x+k])++k;
hei[rk[i]]=k;
}
}
void solve(){
st.push(0);
for(register int i=1;i<=n;++i)
st.push(i),ll[i]=st.back()+1;
st.clear(),st.push(n+1);
for(register int i=n;i;--i)
st.push(i),rr[i]=st.back()-1;
for(register int i=1;i<=n;++i)
ans[hei[i]]=max(ans[hei[i]],rr[i]-ll[i]+2);//先只更新当前答案 ,比hei[i]小的下面做一个后缀最大值取到
ans[n+1]=1;//答案最少为1
for(register int i=n;i;--i)
ans[i]=max(ans[i],ans[i+1]);
for(register int i=1;i<=n;++i)
printf("%d\n",ans[i]);
}
int main(){
scanf("%s",s+1),n=strlen(s+1);
Ssort(),get_height(),solve();
}