上题面有误,应该是最大的最小
考虑二分这个最小的串的排名
那么也就是说所有排名比这个大的一定要被切开
考虑一个后缀
如果那么显然不合法
否则考虑在前切开
考虑从后往前考虑每个后缀
那么显然每次在切开一定就是最优的
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define pic pair<int,char>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>
#define chemx(a,b) ((a)<(b)?(a)=(b):0)
#define chemn(a,b) ((a)>(b)?(a)=(b):0)
cs int N=100005;
namespace Sa{
int n,m,rk[N],sa[N],cnt[N],sa2[N],ht[N],s[N];
inline void buc_sort(){
for(int i=1;i<=m;i++)cnt[i]=0;
for(int i=1;i<=n;i++)cnt[rk[sa2[i]]]++;
for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void buildsa(char *a){
n=strlen(a+1),m=30;
for(int i=1;i<=n;i++)s[i]=a[i]-'a'+1;
for(int i=1;i<=n;i++)rk[i]=s[i],sa2[i]=i;
buc_sort();
for(int pos=0,i=1;i<=n&&pos<n;i<<=1){
pos=0;
for(int j=n-i+1;j<=n;j++)sa2[++pos]=j;
for(int j=1;j<=n;j++)if(sa[j]>i)sa2[++pos]=sa[j]-i;
buc_sort();
swap(rk,sa2);
rk[sa[1]]=1,pos=1;
for(int j=2;j<=n;j++)
rk[sa[j]]=(sa2[sa[j-1]]==sa2[sa[j]]&&sa2[sa[j-1]+i]==sa2[sa[j]+i])?pos:++pos;
m=pos;
}
for(int i=1,j,k=0;i<=n;ht[rk[i++]]=k)
for(k?k--:0,j=sa[rk[i]-1];s[j+k]==s[i+k];k++);
}
int lg[N],st[20][N<<1];
inline void buildst(){
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int i=2;i<=n;i++)st[0][i]=ht[i];
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);
}
inline int Lcp(int x,int y){
if(x==y)return n-x+1;
x=rk[x],y=rk[y];
if(x>y)swap(x,y);x++;
int t=lg[y-x+1];
return min(st[t][x],st[t][y-(1<<t)+1]);
}
inline ll calc(){
ll res=0;
for(int i=1;i<=n;i++)res+=n-sa[i]+1-ht[i];
return res;
}
inline pii getkth(ll k){
ll res=0;
for(int i=1;i<=n;i++){
if(res<k&&res+n-sa[i]+1-ht[i]>=k){
pii now;
now.fi=sa[i];
now.se=k-res+sa[i]+ht[i]-1;
return now;
}
res+=n-sa[i]+1-ht[i];
}
}
inline bool comp(int l1,int r1,int l2,int r2){
int len=min(r1-l1+1,r2-l2+1);
int lcp=Lcp(l1,l2);
if(lcp<len)return s[l1+lcp]<s[l2+lcp];
return r1-l1+1<r2-l2+1;
}
inline bool check(ll k,int tim){
pii now=getkth(k);int last=n+1;
for(int i=n;i;i--){
if(comp(i,n,now.fi,now.se))continue;
int lcp=min(now.se-now.fi+1,Lcp(now.fi,i));
if(lcp==0)return false;
if(i+lcp<last)tim--,last=i+1;
}
if(last>1)tim--;
if(tim<0)return false;
return true;
}
inline void solve(int k){
ll l=1,r=calc(),res=r;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid,k))r=mid-1,res=mid;
else l=mid+1;
}
pii now=getkth(res);
for(int i=now.fi;i<=now.se;i++)putchar(s[i]+'a'-1);
}
}
int n,k;
char s[N];
int main(){
k=read();
scanf("%s",s+1);
n=strlen(s+1);
Sa::buildsa(s);
Sa::buildst();
Sa::solve(k);
}