后缀数组求出height数组
然后扫一边
暴力统计出解就可以了
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define T 3333
using namespace std;
char s[T];
int t1[T],t2[T],cc[T],rank[T],sa[T],height[T];
int len,pre=0;
bool cmp(int *y,int a,int b,int k)
{
int a1=y[a],b1=y[b];
int a2=a+k>=len?-1:y[a+k];
int b2=b+k>=len?-1:y[b+k];
return a1==b1&&a2==b2;
}
void make_sa()
{
int *x=t1,*y=t2,m=255;
for(int i=0;i<m;i++)cc[i]=0;
for(int i=0;i<len;i++)++cc[x[i]=s[i]];
for(int i=1;i<m;i++)cc[i]+=cc[i-1];
for(int i=len-1;~i;i--)sa[--cc[x[i]]]=i;
for(int k=1;k<=len;k<<=1)
{
int p=0;
for(int i=len-k;i<len;i++)y[p++]=i;
for(int i=0;i<len;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
for(int i=0;i<m;i++)cc[i]=0;
for(int i=0;i<len;i++)++cc[x[y[i]]];
for(int i=1;i<m;i++)cc[i]+=cc[i-1];
for(int i=len-1;~i;i--)sa[--cc[x[y[i]]]]=y[i];
swap(x,y),m=1,x[sa[0]]=0;
for(int i=1;i<len;i++)x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?m-1:m++;
if(m>=len)return;
}
}
void make_height()
{
int k=0;
for(int i=0;i<len;i++)rank[sa[i]]=i;
for(int i=0;i<len;i++)
{
if(!rank[i])continue;
int j=sa[rank[i]-1];
if(k)k--;
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
int main()
{
scanf("%d%s",&len,s);
make_sa(),make_height();
for(int i=1;i<len;i++)
{
for(int j=pre+1;j<=height[i];j++)
{
int ans=2,k=i+1;
while(height[k]>=j)k++,ans++;
printf("%d\n",ans);
}
pre=height[i];
}
}