luogu P3975 [TJOI2015]弦論
阿新 • • 發佈:2018-12-16
對原串構建SAM,然後在上面走出這個串,聯絡Splay求第k大,需要知道每個狀態往後走總共有多少子串,這個可以按照拓撲序逆序dp得到(至於dp初始狀態,本質相同子串算一個就為1,否則為endpos的大小)
#include<bits/stdc++.h> #define LL long long #define il inline #define re register #define db double using namespace std; const int N=1000000+10; il LL rd() { LL x=0,w=1;char ch=0; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } char cc[N]; int n,t; int bk[N>>1],aa[N]; int fa[N],len[N],ch[N][26],sz[N],la=1,tt=1; LL a[N],kk; bool v[N]; il void inst(char c,int i) { int np=++tt,p=la; la=np,sz[np]=1,len[np]=len[p]+1; while(p&&!ch[p][c-'a']) ch[p][c-'a']=np,p=fa[p]; if(!p) fa[np]=1; else { int q=ch[p][c-'a']; if(len[q]==len[p]+1) fa[np]=q; else { int nq=++tt; fa[nq]=fa[q],len[nq]=len[p]+1,fa[q]=fa[np]=nq; for(int i=0;i<26;++i) ch[nq][i]=ch[q][i]; while(p&&ch[p][c-'a']==q) ch[p][c-'a']=nq,p=fa[p]; } } } int main() { scanf("%s",cc+1); n=strlen(cc+1); t=rd(),kk=rd(); for(int i=1;i<=n;++i) inst(cc[i],i); for(int i=1;i<=tt;++i) ++bk[len[i]]; for(int i=1;i<=n;++i) bk[i]+=bk[i-1]; for(int i=1;i<=tt;++i) aa[bk[len[i]]--]=i; for(int i=2;i<=tt;++i) a[i]=t?sz[i]:1; for(int i=tt;i;--i) sz[fa[aa[i]]]+=sz[aa[i]]; for(int i=tt;i;--i) for(int j=0;j<26;++j) a[aa[i]]+=a[ch[aa[i]][j]]; if(a[1]<kk) puts("-1"); else { int nw=1; while(kk>0) { LL cn=0; for(int i=0;i<26;++i) { cn+=a[ch[nw][i]]; if(cn>=kk) { putchar('a'+i); nw=ch[nw][i]; kk-=cn-a[nw]+(t?sz[nw]:1); break; } } } putchar('\n'); } return 0; }