Lexicographic rank of a string among all its substrings
Last Updated :
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: 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:
- 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++
// 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>
Time Complexity: O(N3)
Auxiliary Space: O(N)
Similar Reads
Lexicographical concatenation of all substrings of a string Given a string, find the concatenation of all substrings in lexicographic order.Examples:Input : s = "abc"Output : aababcbbccThe substrings of s in lexicographic order are "a", "b", "c", "ab", "abc", "bc". Concatenation of substrings is "a"+"ab"+"abc"+"b"+"bc"+"c" = "aababcbbcc".Input : s = "cba"Out
7 min read
Lexicographic rank of a string using STL You are given a string, find its rank among all its permutations sorted lexicographically. Examples:Input : str[] = "acb"Output : Rank = 2Input : str[] = "string"Output : Rank = 598Input : str[] = "cba"Output : Rank = 6We have already discussed solutions to find Lexicographic rank of string In this
4 min read
Lexicographic rank of a String Given a string str, find its rank among all its permutations when sorted lexicographically.Note: The characters in string are all unique.Examples:Input: str = "acb"Output: 2Explanation: If all the permutations of the string are arranged lexicographically they will be "abc", "acb", "bac", "bca", "cab
15+ min read
Lexicographic rank of a Binary String Given a binary string S of length N, the task is to find the lexicographic rank of the given string. Examples: Input: S = "001"Output: 8Explanation:Strings in order of their increasing rank:"0" = 1, â1â = 2, â00â = 3, â01â = 4, â10â = 5, â11â = 6, â000â = 7, "001" = 8. Input: S = "01"Output: 4 Naive
6 min read
Print all lexicographical greater permutations of a given string Given a string S, print those permutations of string S which are lexicographically greater than S. If there is no such permutation of string, print -1. Examples: Input : BCA Output : CAB, CBA Explanation: Here, S = "BCA", and there are 2 strings "CAB, CBA" which are lexicographically greater than S.
13 min read
Sort a string lexicographically by reversing a substring Given a string S consisting of N lowercase characters, the task is to find the starting and the ending indices ( 0-based indexing ) of the substring of the given string S that needed to be reversed to make the string S sorted. If it is not possible to sort the given string S by reversing any substri
12 min read