Open In App

Lexicographic rank of a string among all its substrings

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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: 7
Explanation:
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: 12
Explanation:
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:

  1. Initialize an array arr[] of vectors of length 26 to store the indices of the characters present in the string and rank as 0.
  2. 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.
  3. Traverse each index stored in the array arr[] up to the characters which are smaller than the first character of the string S.
  4. 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.
  5. Now, after traversing, store all the substrings starting from the first character of S and sort those substrings in lexicographical order.
  6. Traverse the sorted substrings and compare each substring with the string S and increment the rank until substring equals to S is found.
  7. Print the value of rank + 1 to get the rank of the given string.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find lexicographic rank
// of string among all its substring
int 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 Code
int main()
{
    // Given string
    string str = "enren";
 
    // Function Call
    cout << lexicographicRank(str);
 
    return 0;
}


Java




// Java program for
// the above approach
import java.util.*;
class GFG{
 
// Function to find lexicographic rank
// of String among all its subString
static 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 Code
public 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




# Python3 program for the above approach
 
# Function to find lexicographic rank
# of among all its substring
def 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 Code
if __name__ == '__main__':
     
    # Given string
    strr = "enren"
 
    # Function call
    print(lexicographicRank(strr))
 
# This code is contributed by mohit kumar 29


C#




// C# program for
// the above approach
using System;
using System.Collections.Generic;
class GFG{
 
// Function to find lexicographic rank
// of String among all its subString
static 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 Code
public static void Main(String[] args)
{
  // Given String
  String str = "enren";
 
  // Function Call
  Console.Write(lexicographicRank(str.ToCharArray()));
}
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
 
 
// JavaScript program for the above approach
 
// Function to find lexicographic rank
// of string among all its substring
function 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 string
var str = "enren";
 
// Function Call
document.write( lexicographicRank(str));
 
 
</script>


Output: 

7

Time Complexity: O(N3)
Auxiliary Space: O(N)



Last Updated : 14 Sep, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads