Question Link

Ashton appeared for a job interview and is asked the following question. arrange all the distinct substrings of a given string in lexicographical order and concatenate them. print the kth character of the concatenated string. it is assured that given value of K will be valid I. e. there will be a kth character. can you help Ashton out with this?

**Input Format**

First line will contain a number t I. e. Number of test cases.

First line of each test case will contain a string containing characters (A −z) and second line will contain a number K.

**Output Format**

Print kth character (the string is 1 indexed)

**Constraints**

1 ≤ T ≤ 5

1 ≤ length ≤ 105

K will be an appropriate integer.

**Sample input #00**

`1dbac3`

**Sample output #00**

`c`

**Explanation #00**

The substrings when arranged in Lexicographic Order are as follows

`a, ac, b, ba, bac, c, d, db, dba, dbac`

On concatenating them, we get

`aacbbabaccddbdbadbac`

The third character in this string is`c`

And hence the answer.

Question: Give a string, concatenate all the strings in the lexicographically ascending order to get a large string. Evaluate the K character of the string.

Train of Thought: the result after the strings of this string are sorted alphabetically is actually strings numbered by LCP in the suffix array...

**Accepted code:**

1 #include <string> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 6 const int MAX_N = 100005; 7 typedef long long LL; 8 int n, k, sa[MAX_N], rk[MAX_N], lcp[MAX_N], tmp[MAX_N]; 9 10 bool compare_sa(int i, int j) {11 if (rk[i] != rk[j]) return rk[i] < rk[j];12 int ri = i + k <= n ? rk[i + k] : -1;13 int rj = j + k <= n ? rk[j + k] : -1;14 return ri < rj;15 }16 17 void construct_sa(const string &S, int *sa) {18 n = S.length();19 for (int i = 0; i <= n; i++) {20 sa[i] = i;21 rk[i] = (i < n ? S[i] : -1);22 }23 24 for (k = 1; k <= n; k *= 2) {25 sort(sa, sa + n + 1, compare_sa);26 27 tmp[sa[0]] = 0;28 for (int i = 1; i <= n; i++) {29 tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);30 }31 for (int i = 0; i <= n; i++) rk[i] = tmp[i];32 }33 }34 35 void construct_lcp(const string &S, int *sa, int *lcp) {36 n = S.length();37 for (int i = 0; i <= n; i++) rk[sa[i]] = i;38 39 int h = 0;40 lcp[0] = 0;41 for (int i = 0; i < n; i++) {42 int j = sa[rk[i] - 1];43 44 if (h > 0) h--;45 for (; i + h < n && j + h < n; h++) if (S[i + h] != S[j + h]) break;46 47 lcp[rk[i] - 1] = h;48 }49 } 50 51 string S;52 53 void solve(LL k) {54 n = S.length();55 construct_sa(S, sa);56 construct_lcp(S, sa, lcp); 57 58 for (int i = 0; i < n; i++) {59 int L = lcp[i];60 int left = n - sa[i + 1];61 LL sum = (L + 1 + left) * (LL)(left - L) / 2;62 if (k > sum) {k -= sum;}63 else {64 for (int j = L + 1; j <= left; j++) {65 if (k <= j) {66 int index = sa[i + 1] + k;67 cout << S[index - 1] << endl;68 return ;69 } else {70 k -= j;71 }72 }73 }74 }75 }76 int main(void) {77 ios::sync_with_stdio(false);78 int T;79 cin >> T;80 while (T--) {81 LL k;82 cin >> S >> k;83 solve(k);84 }85 return 0;86 }

Hackerrank -- Ashton and string (suffix array)