Skip to content
Related Articles

# Lexicographic rank of a string with duplicate characters

• Difficulty Level : Hard

Given a string s that may have duplicate characters. Find out the lexicographic rank of s. s may consist of lower as well as upper case letters. We consider the lexicographic order of characters as their order of ASCII value. Hence the lexicographical order of characters will be ‘A’, ‘B’, ‘C’, …, ‘Y’, ‘Z’, ‘a’, ‘b’, ‘c’, …, ‘y’, ‘z’.

Examples:

Input : “abab”
Output : 2
Explanation: The lexicographical order is: “aabb”, “abab”, “abba”, “baab”, “baba”, “bbaa”. Hence the rank of “abab” is 2.
Input: “settLe”
Output : 107

Prerequisite: Lexicographic rank of a string

Method:

The method here is a little different from the without repetition version. Here we have to take care of the duplicate characters also. Let’s look at the string “settLe”. It has repetition(2 ‘e’ and 2 ‘t’) as well as upper case letter(‘L’). Total 6 characters and the total number of permutations are 6!/(2!*2!).
Now there are 3 characters(2 ‘e’ and 1 ‘L’) on the right side of ‘s’ which come before ‘s’ lexicographically. If there were no repetition then there would be 3*5! smaller strings which have the first character less than ‘s’. But starting from position 0, till the end there are 2 ‘s’ and 2 ‘t'(i.e. repetitions). Hence, the number of possible smaller permutations with the first letter smaller than ‘s’ are (3*5!)/(2!*2!).
Similarly, if we fix ‘s’ and look at the letters from index 1 to end then there is 1 character(‘L’) lexicographically less than ‘e’. And starting from position 1 there are 2 repeated characters(2 ‘e’ and 2 ‘t’). Hence, the number of possible smaller permutations with first letter ‘s’ and second letter smaller than ‘e’ are (1*4!)/(2!*2!).
Similarly, we can form the following table:

WorkFlow:

```1. Initialize t_count(total count) variable
to 1(as rank starts from 1).
2. Run a loop for every character of the string, string[i]:
(i) using a loop count less_than(number of smaller
characters on the right side of string[i]).
(ii) take one array d_count of size 52 and using a
loop count the frequency of characters starting
from string[i].
(iii) compute the product, d_fac(the product of
factorials of each element of d_count).
(iv) compute (less_than*fac(n-i-1))/(d_fac).
Add it to t_count.
3. return t_count```

## C++

 `// C++ program to find out lexicographic``// rank of a string which may have duplicate``// characters and upper case letters.``#include ``#include ` `using` `namespace` `std;` `// Function to calculate factorial of a number.``long` `long` `fac(``long` `long` `n)``{``    ``if` `(n == 0 or n == 1)``        ``return` `1;``    ``return` `n * fac(n - 1);``}` `// Function to calculate rank of the string.``int` `lexRank(string s)``{``    ``long` `long` `n = s.size();``    ``// Initialize total count to 1.``    ``long` `long` `t_count = 1;` `    ``// loop to calculate number of smaller strings.``    ``for` `(``int` `i = 0; i < n; i++)``    ``{``        ``// Count smaller characters than s[i].``        ``int` `less_than = 0;``        ``for` `(``int` `j = i + 1; j < n; j++)``        ``{``            ``if` `(``int``(s[i]) > ``int``(s[j]))``            ``{``                ``less_than += 1;``            ``}``        ``}` `        ``// Count frequency of duplicate characters.``        ``vector<``int``> d_count(52, 0);` `        ``for` `(``int` `j = i; j < n; j++)``        ``{``            ``// Check whether the character is upper``            ``// or lower case and then increase the``            ``// specific element of the array.``            ``if` `((``int``(s[j]) >= ``'A'``) && ``int``(s[j]) <= ``'Z'``)``                ``d_count[``int``(s[j]) - ``'A'``] += 1;``            ``else``                ``d_count[``int``(s[j]) - ``'a'` `+ 26] += 1;``        ``}` `        ``// Compute the product of the factorials``        ``// of frequency of characters.``        ``long` `long` `d_fac = 1;``        ``for` `(``int` `ele : d_count)``            ``d_fac *= fac(ele);` `        ``// add the number of smaller string``        ``// possible from index i to total count.``        ``t_count += (fac(n - i - 1) * less_than) / d_fac;``    ``}` `    ``return` `(``int``)t_count;``}` `// Driver Code``int` `main()``{``    ``// Test case 1``    ``string s1 = ``"abab"``;``    ``cout << ``"Rank of "` `<< s1 << ``" is: "` `<< lexRank(s1)``         ``<< endl;` `    ``// Test case 2``    ``string s2 = ``"settLe"``;``    ``cout << ``"Rank of "` `<< s2 << ``" is: "` `<< lexRank(s2)``         ``<< endl;` `    ``return` `0;``}`

## Java

 `// Java program to find out lexicographic``// rank of a String which may have duplicate``// characters and upper case letters.``class` `GFG {` `    ``// Function to calculate``    ``// factorial of a number.``    ``static` `long` `fac(``long` `n)``    ``{``        ``if` `(n == ``0` `|| n == ``1``)``            ``return` `1``;``        ``return` `n * fac(n - ``1``);``    ``}` `    ``// Function to calculate``    ``// rank of the String.``    ``static` `int` `lexRank(String s)``    ``{``        ``long` `n = s.length();` `        ``// Initialize total count to 1.``        ``long` `t_count = ``1``;` `        ``// loop to calculate``        ``// number of smaller Strings.``        ``for` `(``int` `i = ``0``; i < n; i++)``        ``{``            ``// Count smaller``            ``// characters than s[i].``            ``long` `less_than = ``0``;``            ``for` `(``int` `j = i + ``1``; j < n; j++)``            ``{``                ``if` `(s.charAt(i)``                    ``> s.charAt(j))``                ``{``                    ``less_than += ``1``;``                ``}``            ``}` `            ``// Count frequency of``            ``// duplicate characters.``            ``long``[] d_count = ``new` `long``[``52``];` `            ``for` `(``int` `j = i; j < n; j++)``            ``{``                ``// Check whether the``                ``// character is upper``                ``// or lower case and``                ``// then increase the``                ``// specific element of``                ``// the array.``                ``if` `((s.charAt(j) >= ``'A'``)``                    ``&& s.charAt(j) <= ``'Z'``)``                    ``d_count[s.charAt(j) - ``'A'``] += ``1``;``                ``else``                    ``d_count[s.charAt(j) - ``'a'` `+ ``26``] += ``1``;``            ``}` `            ``// Compute the product of the factorials``            ``// of frequency of characters.``            ``long` `d_fac = ``1``;``            ``for` `(``long` `ele : d_count)``                ``d_fac *= fac(ele);` `            ``// add the number of smaller String``            ``// possible from index i to total count.``            ``t_count += (fac(n - i - ``1``)``                        ``* less_than) / d_fac;``        ``}``        ``return` `(``int``)t_count;``    ``}` `    ``// Driver Code``    ``public` `static` `void` `main(String[] args)``    ``{``        ``// Test case 1``        ``String s1 = ``"abab"``;``        ``System.out.print(``"Rank of "` `+ s1``                         ``+ ``" is: "` `+ lexRank(s1) + ``"\n"``);` `        ``// Test case 2``        ``String s2 = ``"settLe"``;``        ``System.out.print(``"Rank of "` `+ s2``                         ``+ ``" is: "` `+ lexRank(s2) + ``"\n"``);``    ``}``}` `// This code is contributed by gauravrajput1`

## C#

 `// C# program to find out``// lexicographic rank of a``// String which may have``// duplicate characters and``// upper case letters.``using` `System;``class` `GFG {` `    ``// Function to calculate``    ``// factorial of a number.``    ``static` `long` `fac(``long` `n)``    ``{``        ``if` `(n == 0 || n == 1)``            ``return` `1;``        ``return` `n * fac(n - 1);``    ``}` `    ``// Function to calculate``    ``// rank of the String.``    ``static` `long` `lexRank(String s)``    ``{``        ``long` `n = s.Length;` `        ``// Initialize total``        ``// count to 1.``        ``long` `t_count = 1;` `        ``// loop to calculate number``        ``// of smaller Strings.``        ``for` `(``long` `i = 0; i < n; i++)``        ``{``            ``// Count smaller characters``            ``// than s[i].``            ``long` `less_than = 0;` `            ``for` `(``long` `j = i + 1; j < n; j++)``            ``{``                ``if` `(s[i] > s[j])``                ``{``                    ``less_than += 1;``                ``}``            ``}` `            ``// Count frequency of``            ``// duplicate characters.``            ``long``[] d_count = ``new` `long``[52];` `            ``for` `(``int` `j = i; j < n; j++)``            ``{``                ``// Check whether the character``                ``// is upper or lower case and``                ``// then increase the specific``                ``// element of the array.``                ``if` `((s[j] >= ``'A'``) && s[j] <= ``'Z'``)``                    ``d_count[s[j] - ``'A'``] += 1;``                ``else``                    ``d_count[s[j] - ``'a'` `+ 26] += 1;``            ``}` `            ``// Compute the product of the``            ``// factorials of frequency of``            ``// characters.``            ``long` `d_fac = 1;` `            ``foreach``(``long` `ele ``in` `d_count)``              ``d_fac *= fac(ele);` `            ``// add the number of smaller``            ``// String possible from index``            ``// i to total count.``            ``t_count += (fac(n - i - 1)``                        ``* less_than) / d_fac;``        ``}``        ``return` `t_count;``    ``}` `    ``// Driver Code``    ``public` `static` `void` `Main(String[] args)``    ``{``        ``// Test case 1``        ``String s1 = ``"abab"``;``        ``Console.Write(``"Rank of "` `+ s1``                      ``+ ``" is: "` `+ lexRank(s1) + ``"\n"``);` `        ``// Test case 2``        ``String s2 = ``"settLe"``;``        ``Console.Write(``"Rank of "` `+ s2``                      ``+ ``" is: "` `+ lexRank(s2) + ``"\n"``);``    ``}``}` `// This code is contributed by Rajput-Ji`

## Javascript

 ``
Output
```Rank of abab is: 2
Rank of settLe is: 107```

Time complexity: O(n2)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up