Print Kth character in sorted concatenated substrings of a string | C ++ program to print Kth character in sorted concatenated substrings ; Structure to store information of a suffix ; To store original index ; To store ranks and next ; A comparison function used by sort ( ) to compare two suffixes . Compares two pairs , returns 1 if first pair is smaller ; This is the main function that takes a string ' txt ' of size n as an argument , builds and return the suffix array for the given string ; A structure to store suffixes and their indexes ; Store suffixes and their indexes in an array of structures . The structure is needed to sort the suffixes alphabatically and maintain their old indexes while sorting ; Sort the suffixes using the comparison function defined above . ; At his point , all suffixes are sorted according to first 2 characters . Let us sort suffixes according to first 4 characters , then first 8 and so on This array is needed to get the ; index in suffixes [ ] from original index . This mapping is needed to get next suffix . ; Assigning rank and index values to first suffix ; Assigning rank to suffixes ; If first rank and next ranks are same as that of previous suffix in array , assign the same new rank to this suffix ; Otherwise increment rank and assign ; Assign next rank to every suffix ; Sort the suffixes according to first k characters ; Store indexes of all sorted suffixes in the suffix array ; Return the suffix array ; To construct and return LCP ; To store LCP array ; An auxiliary array to store inverse of suffix array elements . For example if suffixArr [ 0 ] is 5 , the invSuff [ 5 ] would store 0. This is used to get next suffix string from suffix array . ; Fill values in invSuff [ ] ; Initialize length of previous LCP ; Process all suffixes one by one starting from first suffix in txt [ ] ; If the current suffix is at n - 1 , then we dont have next substring to consider . So lcp is not defined for this substring , we put zero . ; j contains index of the next substring to be considered to compare with the present substring , i . e . , next string in suffix array ; Directly start matching from k 'th index as  at-least k-1 characters will match ; lcp for the present suffix . ; Deleting the starting character from the string . ; return the constructed lcp array ; Utility method to get sum of first N numbers ; Returns Kth character in sorted concatenated substrings of str ; calculating suffix array and lcp array ; skipping characters common to substring ( n - suffixArr [ i ] ) is length of current maximum substring lcp [ i ] will length of common substring ; if characters are more than K , that means Kth character belongs to substring corresponding to current lcp [ i ] ; loop from current lcp value to current string length ; Again reduce K by current substring 's  length one by one and when it becomes less,  print Kth character of current substring  ; Driver code to test above methods
#include <bits/stdc++.h> NEW_LINE using namespace std ; struct suffix { int index ; int rank [ 2 ] ; } ; int cmp ( struct suffix a , struct suffix b ) { return ( a . rank [ 0 ] == b . rank [ 0 ] ) ? ( a . rank [ 1 ] < b . rank [ 1 ] ? 1 : 0 ) : ( a . rank [ 0 ] < b . rank [ 0 ] ? 1 : 0 ) ; } vector < int > buildSuffixArray ( string txt , int n ) { struct suffix suffixes [ n ] ; for ( int i = 0 ; i < n ; i ++ ) { suffixes [ i ] . index = i ; suffixes [ i ] . rank [ 0 ] = txt [ i ] - ' a ' ; suffixes [ i ] . rank [ 1 ] = ( ( i + 1 ) < n ) ? ( txt [ i + 1 ] - ' a ' ) : -1 ; } sort ( suffixes , suffixes + n , cmp ) ; int ind [ n ] ; for ( int k = 4 ; k < 2 * n ; k = k * 2 ) { int rank = 0 ; int prev_rank = suffixes [ 0 ] . rank [ 0 ] ; suffixes [ 0 ] . rank [ 0 ] = rank ; ind [ suffixes [ 0 ] . index ] = 0 ; for ( int i = 1 ; i < n ; i ++ ) { if ( suffixes [ i ] . rank [ 0 ] == prev_rank && suffixes [ i ] . rank [ 1 ] == suffixes [ i - 1 ] . rank [ 1 ] ) { prev_rank = suffixes [ i ] . rank [ 0 ] ; suffixes [ i ] . rank [ 0 ] = rank ; } else { prev_rank = suffixes [ i ] . rank [ 0 ] ; suffixes [ i ] . rank [ 0 ] = ++ rank ; } ind [ suffixes [ i ] . index ] = i ; } for ( int i = 0 ; i < n ; i ++ ) { int nextindex = suffixes [ i ] . index + k / 2 ; suffixes [ i ] . rank [ 1 ] = ( nextindex < n ) ? suffixes [ ind [ nextindex ] ] . rank [ 0 ] : -1 ; } sort ( suffixes , suffixes + n , cmp ) ; } vector < int > suffixArr ; for ( int i = 0 ; i < n ; i ++ ) suffixArr . push_back ( suffixes [ i ] . index ) ; return suffixArr ; } vector < int > kasai ( string txt , vector < int > suffixArr ) { int n = suffixArr . size ( ) ; vector < int > lcp ( n , 0 ) ; vector < int > invSuff ( n , 0 ) ; for ( int i = 0 ; i < n ; i ++ ) invSuff [ suffixArr [ i ] ] = i ; int k = 0 ; for ( int i = 0 ; i < n ; i ++ ) { if ( invSuff [ i ] == n - 1 ) { k = 0 ; continue ; } int j = suffixArr [ invSuff [ i ] + 1 ] ; while ( i + k < n && j + k < n && txt [ i + k ] == txt [ j + k ] ) k ++ ; lcp [ invSuff [ i ] ] = k ; if ( k > 0 ) k -- ; } return lcp ; } int sumOfFirstN ( int N ) { return ( N * ( N + 1 ) ) / 2 ; } char printKthCharInConcatSubstring ( string str , int K ) { int n = str . length ( ) ; vector < int > suffixArr = buildSuffixArray ( str , n ) ; vector < int > lcp = kasai ( str , suffixArr ) ; for ( int i = 0 ; i < lcp . size ( ) ; i ++ ) { int charToSkip = sumOfFirstN ( n - suffixArr [ i ] ) - sumOfFirstN ( lcp [ i ] ) ; if ( K <= charToSkip ) { for ( int j = lcp [ i ] + 1 ; j <= ( n - suffixArr [ i ] ) ; j ++ ) { int curSubstringLen = j ; if ( K <= curSubstringLen ) return str [ ( suffixArr [ i ] + K - 1 ) ] ; else K -= curSubstringLen ; } break ; } else K -= charToSkip ; } } int main ( ) { string str = " banana " ; int K = 10 ; cout << printKthCharInConcatSubstring ( str , K ) ; return 0 ; }