题意
求给定字符串的第k大子串
其实知道后缀自动机的性质后推敲一下还是蛮好理解的。他在胡说
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#define N 500010
using namespace std;
struct SAM_{
int next[N<<2][26],fail[N<<2],stp[N<<2],t[N<<2],r[N<<2],p,cnt,f[N<<1],g[N<<1];
SAM_(){p=cnt=1;}
void Extend(int x){
int np=++cnt;stp[np]=stp[p]+1;g[np]=1;
while(p&&!next[p][x]) next[p][x]=np,p=fail[p];
if(!p) fail[np]=1;
else{
int q=next[p][x];
if(stp[q]==stp[p]+1) fail[np]=q;
else{
int nq=++cnt;stp[nq]=stp[p]+1;
memcpy(next[nq],next[q],sizeof(next[q]));
fail[nq]=fail[q];
fail[q]=fail[np]=nq;
while(p&&next[p][x]==q) next[p][x]=nq,p=fail[p];
}
}
p=np;
}
void Samort(){
int i;
for(i=0;i<=cnt;i++) t[i]=0;
for(i=1;i<=cnt;i++) t[stp[i]]++;
for(i=1;i<=cnt;i++) t[i]+=t[i-1];
for(i=cnt;i;i--) r[t[stp[i]]--]=i;
}
void Getsub(bool rec){
for(int i=cnt;i;i--){
int x=r[i];
if(rec) g[fail[x]]+=g[x];
else g[x]=1;
}
g[1]=0;
for(int i=cnt;i;i--){
int x=r[i];f[x]=g[x];
for(int j=0;j<26;j++) f[x]+=f[next[x][j]];
}
}
void Get_kth(int k){
int w=1,i;
if(f[1]<k){puts("-1");return;}
while(1){
if(k<=g[w]) return;
k-=g[w];
for(i=0;i<26;i++)
if(next[w][i])
if(f[next[w][i]]<k) k-=f[next[w][i]]; else break;
if(i>=26) return;
putchar('a'+i);
w=next[w][i];
}
}
}SAM;
int t,k,len;
char A[N];
int main(){
scanf("%s%d%d",A+1,&t,&k);
len=strlen(A+1);
for(int i=1;i<=len;i++) SAM.Extend(A[i]-'a');
SAM.Samort();
SAM.Getsub(t);
SAM.Get_kth(k);
return 0;
}