Lexicographic rank of a string among all its substrings - GeeksforGeeks

14 Sep, 2021
Given string str, the task is to find the rank of the given string among all its substrings arranged lexicographically.
Examples:
Input: S = “enren”Output: 7Explanation:All the possible substrings in the sorted order are {“e”, “e”, “en”, “en”, “enr”, “enre”, “enren”, “n”, “n”, “nr”, “nre”, “nren”, “r”, “re”, “ren”}.Therefore, the rank of the given string “enren” is 7.
Input: S = “geeks”Output: 12Explanation:All possible substrings in the sorted order are {“e”, “e”, “ee”, “eek”, “eeks”, “ek”, “eks”, “g”, “ge”, “gee”, “geek”, “geeks”, “k”, “ks”, “s”}.Therefore, the rank of the given string “geeks” is 12.
Approach: Follow the steps below to solve the problem:
Initialize an array arr[] of vectors of length 26 to store the indices of the characters present in the string and rank as 0.Store the indices of each character. Indices of a will be stored in arr[0], for b, arr[1] will store all its indices, and so on.Traverse each index stored in the array arr[] up to the characters which are smaller than the first character of the string S.For each index i, total substrings starting from that index is N – i. Add N – i to rank as all characters with these indices are smaller.Now, after traversing, store all the substrings starting from the first character of S and sort those substrings in lexicographical order.Traverse the sorted substrings and compare each substring with the string S and increment the rank until substring equals to S is found.Print the value of rank + 1 to get the rank of the given string.
Initialize an array arr[] of vectors of length 26 to store the indices of the characters present in the string and rank as 0.
Store the indices of each character. Indices of a will be stored in arr[0], for b, arr[1] will store all its indices, and so on.
Traverse each index stored in the array arr[] up to the characters which are smaller than the first character of the string S.
For each index i, total substrings starting from that index is N – i. Add N – i to rank as all characters with these indices are smaller.
Now, after traversing, store all the substrings starting from the first character of S and sort those substrings in lexicographical order.
Traverse the sorted substrings and compare each substring with the string S and increment the rank until substring equals to S is found.
Print the value of rank + 1 to get the rank of the given string.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach #include <bits/stdc++.h>using namespace std; // Function to find lexicographic rank// of string among all its substringint lexicographicRank(string s){    // Length of string    int n = s.length();     vector<int> alphaIndex[26];     // Traverse the given string    // and store the indices of    // each character    for (int i = 0; i < s.length(); i++) {         // Extract the index        int x = s[i] - 'a';         // Store it in the vector        alphaIndex[x].push_back(i);    }     // Traverse the alphaIndex array    // lesser than the index of first    // character of given string    int rank = 0;     for (int i = 0; i < 26                    && 'a' + i < s[0];         i++) {         // If alphaIndex[i] size exceeds 0        if (alphaIndex[i].size() > 0) {             // Traverse over the indices            for (int j = 0;                 j < alphaIndex[i].size(); j++) {                 // Add count of substring                // equal to n - alphaIndex[i][j]                rank = rank                       + (n                          - alphaIndex[i][j]);            }        }    }     vector<string> str;     for (int i = 0;         i < alphaIndex[s[0] - 'a'].size();         i++) {         // Store all substrings in a vector        // str starting with the first        // character of the given string        string substring;         int j = alphaIndex[s[0] - 'a'][i];         for (; j < n; j++) {             // Insert the current            // character to substring            substring.push_back(s[j]);             // Store the substring formed            str.push_back(substring);        }    }     // Sort the substring in the    // lexicographical order    sort(str.begin(), str.end());     // Find the rank of given string    for (int i = 0; i < str.size(); i++) {         if (str[i] != s) {             // increase the rank until            // the given string is same            rank++;        }         // If substring is same as        // the given string        else {            break;        }    }     // Add 1 to rank of    // the given string    return rank + 1;} // Driver Codeint main(){    // Given string    string str = "enren";     // Function Call    cout << lexicographicRank(str);     return 0;}
// Java program for// the above approachimport java.util.*;class GFG{ // Function to find lexicographic rank// of String among all its subStringstatic int lexicographicRank(char []s){  // Length of String  int n = s.length;   Vector<Integer> []alphaIndex = new Vector[26];  for (int i = 0; i < alphaIndex.length; i++)    alphaIndex[i] = new Vector<Integer>();     // Traverse the given String  // and store the indices of  // each character  for (int i = 0; i < s.length; i++)  {    // Extract the index    int x = s[i] - 'a';     // Store it in the vector    alphaIndex[x].add(i);  }   // Traverse the alphaIndex array  // lesser than the index of first  // character of given String  int rank = 0;   for (int i = 0; i < 26 &&           'a' + i < s[0]; i++)  {    // If alphaIndex[i] size exceeds 0    if (alphaIndex[i].size() > 0)    {      // Traverse over the indices      for (int j = 0;               j < alphaIndex[i].size();               j++)      {        // Add count of subString        // equal to n - alphaIndex[i][j]        rank = rank + (n - alphaIndex[i].get(j));      }    }  }   Vector<String> str = new Vector<String>();   for (int i = 0;           i < alphaIndex[s[0] - 'a'].size();           i++)  {    // Store all subStrings in a vector    // str starting with the first    // character of the given String    String subString = "";     int j = alphaIndex[s[0] - 'a'].get(i);     for (; j < n; j++)    {      // Insert the current      // character to subString      subString += (s[j]);       // Store the subString formed      str.add(subString);    }  }   // Sort the subString in the  // lexicographical order  Collections.sort(str);   // Find the rank of given String  for (int i = 0; i < str.size(); i++)  {    if (!str.get(i).equals(String.valueOf(s)))    {      // increase the rank until      // the given String is same      rank++;    }     // If subString is same as    // the given String    else    {      break;    }  }   // Add 1 to rank of  // the given String  return rank + 1;} // Driver Codepublic static void main(String[] args){  // Given String  String str = "enren";   // Function Call  System.out.print(lexicographicRank(str.toCharArray()));}} // This code is contributed by shikhasingrajput
# Python3 program for the above approach # Function to find lexicographic rank# of among all its substringdef lexicographicRank(s):         # Length of string    n = len(s)     alphaIndex = [[] for i in range(26)]     # Traverse the given string    # and store the indices of    # each character    for i in range(len(s)):         # Extract the index        x = ord(s[i]) - ord('a')         # Store it in the vector        alphaIndex[x].append(i)     # Traverse the alphaIndex array    # lesser than the index of first    # character of given string    rank = -1     for i in range(26):        if ord('a') + i >= ord(s[0]):            break         # If alphaIndex[i] size exceeds 0        if len(alphaIndex[i]) > 0:             # Traverse over the indices            for j in range(len(alphaIndex[i])):                 # Add count of substring                # equal to n - alphaIndex[i][j]                rank = rank + (n - alphaIndex[i][j])                     # print(rank)    strr = []     for i in range(len(alphaIndex[ord(s[0]) - ord('a')])):         # Store all substrings in a vector        # strr starting with the first        # character of the given string        substring = []         jj = alphaIndex[ord(s[0]) - ord('a')][i]         for j in range(jj, n):             # Insert the current            # character to substring            substring.append(s[j])             # Store the subformed            strr.append(substring)     # Sort the substring in the    # lexicographical order    strr = sorted(strr)     # Find the rank of given string    for i in range(len(strr)):        if (strr[i] != s):             # Increase the rank until            # the given is same            rank += 1         # If substring is same as        # the given string        else:            break     # Add 1 to rank of    # the given string    return rank + 1 # Driver Codeif __name__ == '__main__':         # Given string    strr = "enren"     # Function call    print(lexicographicRank(strr)) # This code is contributed by mohit kumar 29
// C# program for// the above approachusing System;using System.Collections.Generic;class GFG{ // Function to find lexicographic rank// of String among all its subStringstatic int lexicographicRank(char []s){  // Length of String  int n = s.Length;   List<int> []alphaIndex = new List<int>[26];  for (int i = 0; i < alphaIndex.Length; i++)    alphaIndex[i] = new List<int>();   // Traverse the given String  // and store the indices of  // each character  for (int i = 0; i < s.Length; i++)  {    // Extract the index    int x = s[i] - 'a';     // Store it in the vector    alphaIndex[x].Add(i);  }   // Traverse the alphaIndex array  // lesser than the index of first  // character of given String  int rank = 0;   for (int i = 0; i < 26 &&           'a' + i < s[0]; i++)  {    // If alphaIndex[i] size exceeds 0    if (alphaIndex[i].Count > 0)    {      // Traverse over the indices      for (int j = 0;               j < alphaIndex[i].Count; j++)      {        // Add count of subString        // equal to n - alphaIndex[i,j]        rank = rank + (n - alphaIndex[i][j]);      }    }  }   List<String> str = new List<String>();   for (int i = 0;           i < alphaIndex[s[0] - 'a'].Count; i++)  {    // Store all subStrings in a vector    // str starting with the first    // character of the given String    String subString = "";     int j = alphaIndex[s[0] - 'a'][i];     for (; j < n; j++)    {      // Insert the current      // character to subString      subString += (s[j]);       // Store the subString formed      str.Add(subString);    }  }   // Sort the subString in the  // lexicographical order  str.Sort();   // Find the rank of given String  for (int i = 0; i < str.Count; i++)  {    if (!str[i].Equals(String.Join("", s)))    {      // increase the rank until      // the given String is same      rank++;    }     // If subString is same as    // the given String    else    {      break;    }  }   // Add 1 to rank of  // the given String  return rank + 1;} // Driver Codepublic static void Main(String[] args){  // Given String  String str = "enren";   // Function Call  Console.Write(lexicographicRank(str.ToCharArray()));}} // This code is contributed by 29AjayKumar
<script>  // JavaScript program for the above approach // Function to find lexicographic rank// of string among all its substringfunction lexicographicRank(s){    // Length of string    var n = s.length;     var alphaIndex = Array.from(Array(26),    ()=>new Array());     // Traverse the given string    // and store the indices of    // each character    for (var i = 0; i < s.length; i++) {         // Extract the index        var x = s[i].charCodeAt(0) -               'a'.charCodeAt(0);         // Store it in the vector        alphaIndex[x].push(i);    }     // Traverse the alphaIndex array    // lesser than the index of first    // character of given string    var rank = 0;     for (var i = 0; i < 26         && 'a'.charCodeAt(0) +         i < s[0].charCodeAt(0);         i++) {         // If alphaIndex[i] size exceeds 0        if (alphaIndex[i].length > 0) {             // Traverse over the indices            for (var j = 0;                 j < alphaIndex[i].length; j++) {                 // Add count of substring                // equal to n - alphaIndex[i][j]                rank = rank                       + (n                          - alphaIndex[i][j]);            }        }    }     var str = [];     for (var i = 0;         i < alphaIndex[s[0].charCodeAt(0) -         'a'.charCodeAt(0)].length;         i++) {         // Store all substrings in a vector        // str starting with the first        // character of the given string        var substring = "";         var j = alphaIndex[s[0].charCodeAt(0) -        'a'.charCodeAt(0)][i];         for (; j < n; j++) {             // Insert the current            // character to substring            substring+=(s[j]);             // Store the substring formed            str.push(substring);        }    }     // Sort the substring in the    // lexicographical order    str.sort();     // Find the rank of given string    for (var i = 0; i < str.length; i++) {         if (str[i] != s) {             // increase the rank until            // the given string is same            rank++;        }         // If substring is same as        // the given string        else {            break;        }    }     // Add 1 to rank of    // the given string    return rank + 1;} // Driver Code // Given stringvar str = "enren"; // Function Calldocument.write( lexicographicRank(str));  </script>
7
Time Complexity: O(N3)Auxiliary Space: O(N)
mohit kumar 29
shikhasingrajput
29AjayKumar
rutvik_56
saurabh1990aror
ruhelaa48
adnanirshad158
kalrap615
frequency-counting
lexicographic-ordering
substring
Hash
Mathematical
Searching
Sorting
Strings
Searching
Hash
Strings
Mathematical
Sorting
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Rearrange an array such that arr[i] = i
Count number of times each Edge appears in all possible paths of a given Tree
Design a data structure that supports insert, delete, search and getRandom in constant time
Quadratic Probing in Hashing
Hashing in Java
Program for Fibonacci numbers
Write a program to print all permutations of a given string
C++ Data Types
Set in C++ Standard Template Library (STL)
Coin Change | DP-7