P3975 [TJOI2015]弦论
在原串所有子串中求字典序第k大的子串
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e6+5; 4 char s[maxn]; 5 int a[maxn], c[maxn], size[maxn], sum[maxn], k, t; 6 struct SuffixAutoMaton { 7 int last, cnt; 8 int ch[maxn*2][26], fa[maxn*2], len[maxn*2]; 9 void ins(int c) { 10 int p = last, np = ++cnt; 11 last = np; len[np] = len[p]+1; 12 for (;p && !ch[p][c]; p = fa[p]) ch[p][c] = np; 13 if (!p) fa[np] = 1; 14 else { 15 int q = ch[p][c]; 16 if (len[p]+1 == len[q]) fa[np] = q; 17 else { 18 int nq = ++cnt; 19 len[nq] = len[p]+1; 20 memcpy(ch[nq],ch[q],sizeof(ch[q])); 21 fa[nq] = fa[q]; fa[q] = fa[np] = nq; 22 for (; ch[p][c] == q; p = fa[p]) ch[p][c] = nq; 23 } 24 } 25 size[np] = 1; 26 } 27 void build() { 28 scanf("%s",s+1); 29 int lens = strlen(s+1); 30 last = cnt = 1; 31 for (int i = 1; i <= lens; i++) ins(s[i]-'a'); 32 } 33 void work() { 34 for (int i = 1; i <= cnt; i++) c[len[i]]++; 35 for (int i = 1; i <= cnt; i++) c[i] += c[i-1]; 36 for (int i = 1; i <= cnt; i++) a[c[len[i]]--] = i; 37 for (int i = cnt; i; i--) { 38 int p = a[i]; 39 if (t == 1) size[fa[p]] += size[p]; 40 else size[p] = 1; 41 } 42 size[1] = 0; 43 for (int i = cnt; i; i--) { 44 sum[a[i]] = size[a[i]]; 45 for (int j = 0; j < 26; j++) { 46 if (ch[a[i]][j]) sum[a[i]] += sum[ch[a[i]][j]]; 47 } 48 } 49 } 50 void solve() { 51 if (k > sum[1]) { 52 puts("-1"); 53 return; 54 } 55 int now = 1; 56 k -= size[now]; 57 while (k > 0) { 58 int p = 0; 59 while (k > sum[ch[now][p]]) { 60 k -= sum[ch[now][p]]; 61 p++; 62 } 63 now = ch[now][p]; 64 putchar('a'+p); 65 k -= size[now]; 66 } 67 return; 68 } 69 }sam; 70 int main() { 71 sam.build(); 72 scanf("%d%d",&t,&k); 73 sam.work(); 74 sam.solve(); 75 return 0; 76 }