Link
先求SA,并求出本质不同的子串数目。
然后二分答案(mid),并求出排名为(mid)的子串(t)。
检验从后往前贪心,尽可能地让最后一个(suf)更长。
#include<cstdio>
#include<numeric>
#include<cstring>
#include<algorithm>
typedef long long i64;
const int N=100007;
char str[N+10];
int n,k,sa[N],rank[N],h[N],s[N<<1],t[N<<1],pos[N<<1],r[N>>1],c[N>>1],f[16][N],g[N],Log[N];
i64 L,R;int ansl,ansr,nowl,nowr,len;
#define is(x,a) sa[r[s[x]]a]=x
#define IS(S)
memset(sa+1,0,n<<2),memset(c+1,0,m<<2);
for(int i=1;i<=n;++c[s[i++]]);
std::partial_sum(c+1,c+m+1,c+1),memcpy(r+1,c+1,m<<2);
for(int i=N;i;--i) is(S[i],--);
for(int i=1;i<=m;++i) r[i]=c[i-1]+1;
for(int i=1;i<=n;++i) if(sa[i]>1&&t[sa[i]-1]) is(sa[i]-1,++);
memcpy(r+1,c+1,m<<2);
for(int i=n;i;--i) if(sa[i]>1&&!t[sa[i]-1]) is(sa[i]-1,--);
void SAIS(int n,int m,int*s,int*t,int*pos)
{
int N=0,M=rank[1]=0,*S=s+n;
t[n]=0;
for(int i=n-1;i;--i) t[i]=s[i]^s[i+1]? s[i]>s[i+1]:t[i+1];
for(int i=2;i<=n;++i) rank[i]=t[i-1]&&!t[i]? pos[++N]=i,N:0;
IS(pos);
for(int i=1,x,y=0;i<=n;++i)
if((x=rank[sa[i]]))
{
if(M<=1||pos[x+1]-pos[x]!=pos[y+1]-pos[y]) ++M;
else for(int a=pos[x],b=pos[y];a<=pos[x+1];++a,++b) if((s[a]<<1|t[a])^(s[b]<<1|t[b])) {++M;break;}
S[y=x]=M;
}
if(M^N) SAIS(N,M,S,t+n,pos+n); else for(int i=1;i<=N;++i) sa[S[i]]=i;
for(int i=1;i<=N;++i) S[i]=pos[sa[i]];
IS(S);
}
int lcp(int x,int y){if(x==y) return n-x;x=rank[x],y=rank[y];if(x>y) std::swap(x,y);int k=Log[y-x];return std::min(f[k][x+1],f[k][y-(1<<k)+1]);}
void work(i64 lim)
{
i64 s=0;
for(int i=1;i<=n;s+=n+1-sa[i]-h[i],++i) if(s+n+1-sa[i]-h[i]>=lim) return nowl=sa[i],nowr=nowl+h[i]+lim-s-1,len=nowr-nowl+1,void();
}
int ask(int l,int r)
{
int t=std::min(lcp(l,nowl),std::min(r-l+1,len));
if(t==r-l+1&&t<=len) return 1;
if(t==len) return 0;
return str[l+t]<=str[nowl+t];
}
int check()
{
int c=0;
for(int i=n,j;i;i=j,++c)
{
for(j=i;j;--j) if(!ask(j,i)) break;
if(j==i) return 0;
}
return c<=k;
}
int main()
{
scanf("%d%s",&k,str+1),n=strlen(str+1),R=1ll*n*(n+1)/2;
for(int i=1;i<=n;++i) s[i]=str[i]-'a'+2;
s[++n]=1,SAIS(n--,27,s,t,pos);
for(int i=1;i<=n;++i) rank[sa[i]=sa[i+1]]=i;
for(int i=1,j,l=0;i<=n;h[rank[i++]]=l) for(j=sa[~-rank[i]],l-=l>0;i+l<=n&&j+l<=n&&s[i+l]==s[j+l];++l);
for(int i=2;i<=n;++i) Log[i]=Log[i>>1]+1;
for(int i=1;i<=n;++i) f[0][i]=h[i];
for(int j=1;j<17;++j) for(int i=1,d=1<<(j-1);i+d<=n;++i) f[j][i]=std::min(f[j-1][i],f[j-1][i+d]);
for(int i=2;i<=n;++i) R-=h[i];
for(i64 mid;L<=R;) work(mid=(L+R)>>1),check()? ansl=nowl,ansr=nowr,R=mid-1:L=mid+1;
for(int i=ansl;i<=ansr;++i) putchar(str[i]);
}