咱們先求出該字符串的\(SA\)和\(Ht\)ios
而後分類討論spa
\(T=0\)時,每次去掉\(Ht\)日後掃就行code
\(T=1\)時,咱們考慮\(lcp\)對答案的影響字符串
既然用到\(lcp\),那就要用\(ST\)表維護string
左端點固定時,隨右端點的增大,區間\(\min\)單調不升it
咱們就能夠用二分+限制右端點的方式統計某個後綴的前綴的貢獻io
循環遍歷每一個後綴時,因爲\(Ht\)部分已經統計過對答案的貢獻,就不用再計算了,從\(Ht+1\)的位置繼續向後統計便可class
#include"cstdio" #include"cstring" #include"iostream" #include"algorithm" using namespace std; const int MAXN=5e5+5; int ln,maxn,p,t; int SA[MAXN],id[MAXN],rnk[MAXN],bnk[MAXN],Ht[MAXN]; char ch[MAXN]; int ST[19][MAXN],lg[MAXN]; void shel() { for(int i=1;i<=ln;++i) ++bnk[rnk[id[i]]]; for(int i=1;i<=maxn;++i) bnk[i]+=bnk[i-1]; for(int i=1;i<=ln;++i) SA[++bnk[rnk[id[i]]-1]]=id[i]; for(int i=0;i<=maxn;++i) bnk[i]=0; return; } void GetSA() { for(int i=1;i<=ln;++i) rnk[i]=ch[i],id[i]=i,maxn=max(maxn,rnk[i]); shel(); for(int k=1;k<ln;k<<=1){ for(int i=1;i<=k;++i) id[i]=ln-k+i; int ct=k; for(int i=1;i<=ln;++i) if(SA[i]>k) id[++ct]=SA[i]-k; shel();swap(id,rnk);rnk[SA[1]]=1; for(int i=2;i<=ln;++i) rnk[SA[i]]=(id[SA[i]]==id[SA[i-1]]&&id[SA[i]+k]==id[SA[i-1]+k])?rnk[SA[i-1]]:rnk[SA[i-1]]+1; if(rnk[SA[ln]]==ln) return; maxn=rnk[SA[ln]]; }return; } void GetHt() { int k=0; for(int i=1;i<=ln;++i){ if(rnk[i]==1) continue; if(k) --k; int ct=SA[rnk[i]-1]; while(ct+k<=ln&&i+k<=ln&&ch[i+k]==ch[ct+k]) ++k; Ht[rnk[i]]=k; }return; } int Getmi(int l,int r){int tmp=lg[r-l+1];return min(ST[tmp][l+(1<<tmp)-1],ST[tmp][r]);} void slv1() { for(int i=1;i<=ln;++i) lg[i]=i>>lg[i-1]+1?lg[i-1]+1:lg[i-1]; for(int i=1;i<=ln;++i) ST[0][i]=Ht[i]; for(int j=1;j<=lg[ln];++j){ int tmp=1<<j-1; for(int i=tmp<<1;i<=ln;++i){ ST[j][i]=min(ST[j-1][i],ST[j-1][i-tmp]); } }for(int i=1;i<=ln;++i){ int tmp=SA[i]+Ht[i]; int ct=ln; while(1){ if(tmp>ln) break; if(ct==i){ if(t>ln-tmp+1){t-=ln-tmp+1;break;} for(int j=SA[i];j<=tmp+t-1;++j) putchar(ch[j]); return; }int l=i,r=ct; while(l<r){ int mid=l+r+1>>1; if(Getmi(i+1,mid)>=tmp-SA[i]+1) l=mid; else r=mid-1; }ct=r; if(t>r-i+1) t-=r-i+1; else{ for(int j=SA[i];j<=tmp;++j) putchar(ch[j]); return; }++tmp; } }puts("-1"); return; } void slv2() { int ct=1; while(t>ln-SA[ct]-Ht[ct]+1) t-=ln-SA[ct]-Ht[ct]+1,++ct; if(ct>ln){puts("-1");return;} for(int i=SA[ct];i<=SA[ct]+t+Ht[ct]-1;++i) putchar(ch[i]); puts(""); return; } int main() { scanf("%s",ch+1);ln=strlen(ch+1); GetSA();GetHt();scanf("%d%d",&p,&t); p?slv1():slv2(); return 0; }