Description
对于一个给定长度为N的字符串,求它的第K小子串是什么。
Input
第一行是一个仅由小写英文字母构成的字符串S
第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。
Output
输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1
Sample Input
aabc
0 3
Sample Output
aab
HINT
1 #include<cstdio>
2 #include<cstring>
3 using namespace std;
4
5 const int N = 5*1e5+10;
6
7 char s[N];
8 int root,last,sz,ch[N][26],fa[N],sum[N],val[N],l[N];
9 void add(int x) {
10 int c=s[x]-‘a‘;
11 int p=last,np=++sz; last=np;
12 l[np]=x+1; val[np]=1;
13 for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
14 if(!p) fa[np]=root;
15 else {
16 int q=ch[p][c];
17 if(l[p]+1==l[q]) fa[np]=q;
18 else {
19 int nq=++sz; l[nq]=l[p]+1;
20 memcpy(ch[nq],ch[q],sizeof(ch[q]));
21 fa[nq]=fa[q];
22 fa[np]=fa[q]=nq;
23 for(;p&&q==ch[p][c];p=fa[p]) ch[p][c]=nq;
24 }
25 }
26 }
27
28 int n,T,b[N],cnt[N];
29
30 void get_sum() {
31 for(int i=1;i<=sz;i++) cnt[l[i]]++;
32 for(int i=1;i<=n;i++) cnt[i]+=cnt[i-1];
33 for(int i=sz;i>=1;i--) b[cnt[l[i]]--]=i;
34 for(int i=sz;i;i--)
35 if(!T) val[b[i]]=1;
36 else val[fa[b[i]]]+=val[b[i]];
37 val[1]=0;
38 for(int i=sz;i;i--) {
39 int p=b[i]; sum[p]=val[p];
40 for(int j=0;j<26;j++)
41 sum[p]+=sum[ch[p][j]];
42 }
43 }
44
45 int main() {
46 scanf("%s",s);
47 n=strlen(s);
48 root=last=++sz;
49 for(int i=0;i<n;i++) add(i);
50 scanf("%d",&T);
51 int x,p=root; scanf("%d",&x);
52 get_sum();
53 if(x>sum[1]) { puts("-1");return 0; }
54 while(x>val[p]) {
55 for(int c=0;c<26;c++)if(ch[p][c]) {
56 if(sum[ch[p][c]]>=x) {
57 putchar(‘a‘+c);
58 x-=val[p]; p=ch[p][c];
59 break;
60 }
61 else x-=sum[ch[p][c]];
62 }
63 }
64 return 0;
65 }