📜  字符串的词法等级

📅  最后修改于: 2021-05-04 19:50:49             🧑  作者: Mango

给定一个字符串,可以在按字典顺序排序的所有排列中找到其排名。例如,“ abc”的等级为1,“ acb”的等级为2,而“ cba”的等级为6。

例子:

Input : str[] = "acb"
Output : Rank = 2

Input : str[] = "string"
Output : Rank = 598

Input : str[] = "cba"
Output : Rank = 6

为简单起见,让我们假设该字符串不包含任何重复的字符。

一种简单的解决方案是将等级初始化为1,以字典顺序生成所有排列。生成排列后,检查生成的排列是否与给定的字符串相同,如果相同,则返回等级,如果不相同,则将等级增加1。在最坏的情况下,此解决方案的时间复杂度将是指数级的。以下是有效的解决方案。

让给定的字符串为“ STRING”。在输入字符串,“ S”是第一个字符。共有6个字符,其中4个字符小于“ S”。这样就可以有4 * 5!较小的字符串,其中第一个字符小于“ S”,如下所示
RXXXX X
IXXXX X
NXXXX X
GXXXXX
现在让我们修复S’并找到以’S’开头的较小字符串。

对T重复相同的过程,等级为4 * 5! + 4 * 4! +…

现在修复T并对R重复相同的过程,等级是4 * 5! + 4 * 4! + 3 * 3! +…

现在修复R并为I重复相同的过程,等级为4 * 5! + 4 * 4! + 3 * 3! + 1 * 2! +…

现在修复I并对N重复相同的过程,等级为4 * 5! + 4 * 4! + 3 * 3! + 1 * 2! + 1 * 1! +…

现在修复N,并对G重复相同的过程,等级为4 * 5! + 4 * 4! + 3 * 3! + 1 * 2! + 1 * 1! + 0 * 0!

等级= 4 * 5! + 4 * 4! + 3 * 3! + 1 * 2! + 1 * 1! + 0 * 0! = 597

请注意,以上计算发现了较小字符串。因此,给定字符串的等级是较小字符串加1。最终等级= 1 + 597 = 598

下面是上述方法的实现:

C++
// C++ program to find lexicographic rank
// of a string
#include 
#include 
 
using namespace std;
// A utility function to find factorial of n
int fact(int n)
{
    return (n <= 1) ? 1 : n * fact(n - 1);
}
 
// A utility function to count smaller characters on right
// of arr[low]
int findSmallerInRight(char* str, int low, int high)
{
    int countRight = 0, i;
 
    for (i = low + 1; i <= high; ++i)
        if (str[i] < str[low])
            ++countRight;
 
    return countRight;
}
 
// A function to find rank of a string in all permutations
// of characters
int findRank(char* str)
{
    int len = strlen(str);
    int mul = fact(len);
    int rank = 1;
    int countRight;
 
    int i;
    for (i = 0; i < len; ++i) {
        mul /= len - i;
 
        // count number of chars smaller than str[i]
        // from str[i+1] to str[len-1]
        countRight = findSmallerInRight(str, i, len - 1);
 
        rank += countRight * mul;
    }
 
    return rank;
}
 
// Driver program to test above function
int main()
{
    char str[] = "string";
    cout << findRank(str);
    return 0;
}
 
// This code is contributed
// by Akanksha Rai


C
// C program to find lexicographic rank
// of a string
#include 
#include 
 
// A utility function to find factorial of n
int fact(int n)
{
    return (n <= 1) ? 1 : n * fact(n - 1);
}
 
// A utility function to count smaller characters on right
// of arr[low]
int findSmallerInRight(char* str, int low, int high)
{
    int countRight = 0, i;
 
    for (i = low + 1; i <= high; ++i)
        if (str[i] < str[low])
            ++countRight;
 
    return countRight;
}
 
// A function to find rank of a string in all permutations
// of characters
int findRank(char* str)
{
    int len = strlen(str);
    int mul = fact(len);
    int rank = 1;
    int countRight;
 
    int i;
    for (i = 0; i < len; ++i) {
        mul /= len - i;
 
        // count number of chars smaller than str[i]
        // fron str[i+1] to str[len-1]
        countRight = findSmallerInRight(str, i, len - 1);
 
        rank += countRight * mul;
    }
 
    return rank;
}
 
// Driver program to test above function
int main()
{
    char str[] = "string";
    printf("%d", findRank(str));
    return 0;
}


Java
// Java program to find lexicographic rank
// of a string
import java.io.*;
import java.util.*;
 
class GFG {
 
    // A utility function to find factorial of n
    static int fact(int n)
    {
        return (n <= 1) ? 1 : n * fact(n - 1);
    }
 
    // A utility function to count smaller
    // characters on right of arr[low]
    static int findSmallerInRight(String str, int low,
                                  int high)
    {
        int countRight = 0, i;
 
        for (i = low + 1; i <= high; ++i)
            if (str.charAt(i) < str.charAt(low))
                ++countRight;
 
        return countRight;
    }
 
    // A function to find rank of a string in
    // all permutations of characters
    static int findRank(String str)
    {
        int len = str.length();
        int mul = fact(len);
        int rank = 1;
        int countRight;
 
        for (int i = 0; i < len; ++i) {
            mul /= len - i;
 
            // count number of chars smaller
            // than str[i] from str[i+1] to
            // str[len-1]
            countRight = findSmallerInRight(str, i, len - 1);
 
            rank += countRight * mul;
        }
 
        return rank;
    }
 
    // Driver program to test above function
    public static void main(String[] args)
    {
        String str = "string";
        System.out.println(findRank(str));
    }
}
 
// This code is contributed by Nikita Tiwari.


Python
# Python program to find lexicographic
# rank of a string
 
# A utility function to find factorial
# of n
def fact(n) :
    f = 1
    while n >= 1 :
        f = f * n
        n = n - 1
    return f
     
# A utility function to count smaller
# characters on right of arr[low]
def findSmallerInRight(st, low, high) :
     
    countRight = 0
    i = low + 1
    while i <= high :
        if st[i] < st[low] :
            countRight = countRight + 1
        i = i + 1
  
    return countRight
     
# A function to find rank of a string
# in all permutations of characters
def findRank (st) :
    ln = len(st)
    mul = fact(ln)
    rank = 1
    i = 0
  
    while i < ln :
         
        mul = mul / (ln - i)
         
        # count number of chars smaller
        # than str[i] fron str[i + 1] to
        # str[len-1]
        countRight = findSmallerInRight(st, i, ln-1)
  
        rank = rank + countRight * mul
        i = i + 1
         
    return rank
     
     
# Driver program to test above function
st = "string"
print (findRank(st))
 
# This code is contributed by Nikita Tiwari.


C#
// C# program to find lexicographic rank
// of a string
using System;
 
class GFG {
 
    // A utility function to find factorial of n
    static int fact(int n)
    {
        return (n <= 1) ? 1 : n * fact(n - 1);
    }
 
    // A utility function to count smaller
    // characters on right of arr[low]
    static int findSmallerInRight(string str,
                                  int low, int high)
    {
        int countRight = 0, i;
 
        for (i = low + 1; i <= high; ++i)
            if (str[i] < str[low])
                ++countRight;
 
        return countRight;
    }
 
    // A function to find rank of a string in
    // all permutations of characters
    static int findRank(string str)
    {
        int len = str.Length;
        int mul = fact(len);
        int rank = 1;
        int countRight;
 
        for (int i = 0; i < len; ++i) {
            mul /= len - i;
 
            // count number of chars smaller
            // than str[i] from str[i+1] to
            // str[len-1]
            countRight = findSmallerInRight(str,
                                            i, len - 1);
 
            rank += countRight * mul;
        }
 
        return rank;
    }
 
    // Driver program to test above function
    public static void Main()
    {
        string str = "string";
        Console.Write(findRank(str));
    }
}
 
// This code is contributed nitin mittal.


PHP


Javascript


C++
// A O(n) solution for finding rank of string
#include 
using namespace std;
#define MAX_CHAR 256
 
// A utility function to find factorial of n
int fact(int n)
{
    return (n <= 1) ? 1 : n * fact(n - 1);
}
 
// Construct a count array where value at every index
// contains count of smaller characters in whole string
void populateAndIncreaseCount(int* count, char* str)
{
    int i;
 
    for (i = 0; str[i]; ++i)
        ++count[str[i]];
 
    for (i = 1; i < MAX_CHAR; ++i)
        count[i] += count[i - 1];
}
 
// Removes a character ch from count[] array
// constructed by populateAndIncreaseCount()
void updatecount(int* count, char ch)
{
    int i;
    for (i = ch; i < MAX_CHAR; ++i)
        --count[i];
}
 
// A function to find rank of a string in all permutations
// of characters
int findRank(char* str)
{
    int len = strlen(str);
    int mul = fact(len);
    int rank = 1, i;
 
    // all elements of count[] are initialized with 0
    int count[MAX_CHAR] = { 0 };
 
    // Populate the count array such that count[i]
    // contains count of characters which are present
    // in str and are smaller than i
    populateAndIncreaseCount(count, str);
 
    for (i = 0; i < len; ++i) {
        mul /= len - i;
 
        // count number of chars smaller than str[i]
        // fron str[i+1] to str[len-1]
        rank += count[str[i] - 1] * mul;
 
        // Reduce count of characters greater than str[i]
        updatecount(count, str[i]);
    }
 
    return rank;
}
 
// Driver program to test above function
int main()
{
    char str[] = "string";
    cout << findRank(str);
    return 0;
}
 
// This is code is contributed by rathbhupendra


C
// A O(n) solution for finding rank of string
#include 
#include 
#define MAX_CHAR 256
 
// A utility function to find factorial of n
int fact(int n)
{
    return (n <= 1) ? 1 : n * fact(n - 1);
}
 
// Construct a count array where value at every index
// contains count of smaller characters in whole string
void populateAndIncreaseCount(int* count, char* str)
{
    int i;
 
    for (i = 0; str[i]; ++i)
        ++count[str[i]];
 
    for (i = 1; i < MAX_CHAR; ++i)
        count[i] += count[i - 1];
}
 
// Removes a character ch from count[] array
// constructed by populateAndIncreaseCount()
void updatecount(int* count, char ch)
{
    int i;
    for (i = ch; i < MAX_CHAR; ++i)
        --count[i];
}
 
// A function to find rank of a string in all permutations
// of characters
int findRank(char* str)
{
    int len = strlen(str);
    int mul = fact(len);
    int rank = 1, i;
 
    // all elements of count[] are initialized with 0
    int count[MAX_CHAR] = { 0 };
 
    // Populate the count array such that count[i]
    // contains count of characters which are present
    // in str and are smaller than i
    populateAndIncreaseCount(count, str);
 
    for (i = 0; i < len; ++i) {
        mul /= len - i;
 
        // count number of chars smaller than str[i]
        // fron str[i+1] to str[len-1]
        rank += count[str[i] - 1] * mul;
 
        // Reduce count of characters greater than str[i]
        updatecount(count, str[i]);
    }
 
    return rank;
}
 
// Driver program to test above function
int main()
{
    char str[] = "string";
    printf("%d", findRank(str));
    return 0;
}


Java
// A O(n) solution for finding rank of string
 
class GFG {
 
    static int MAX_CHAR = 256;
 
    // A utility function to find factorial of n
    static int fact(int n)
    {
        return (n <= 1) ? 1 : n * fact(n - 1);
    }
 
    // Construct a count array where value at every index
    // contains count of smaller characters in whole string
    static void populateAndIncreaseCount(int[] count, char[] str)
    {
        int i;
 
        for (i = 0; i < str.length; ++i)
            ++count[str[i]];
 
        for (i = 1; i < MAX_CHAR; ++i)
            count[i] += count[i - 1];
    }
 
    // Removes a character ch from count[] array
    // constructed by populateAndIncreaseCount()
    static void updatecount(int[] count, char ch)
    {
        int i;
        for (i = ch; i < MAX_CHAR; ++i)
            --count[i];
    }
 
    // A function to find rank of a string in all permutations
    // of characters
    static int findRank(char[] str)
    {
        int len = str.length;
        int mul = fact(len);
        int rank = 1, i;
 
        // all elements of count[] are initialized with 0
        int count[] = new int[MAX_CHAR];
 
        // Populate the count array such that count[i]
        // contains count of characters which are present
        // in str and are smaller than i
        populateAndIncreaseCount(count, str);
 
        for (i = 0; i < len; ++i) {
            mul /= len - i;
 
            // count number of chars smaller than str[i]
            // fron str[i+1] to str[len-1]
            rank += count[str[i] - 1] * mul;
 
            // Reduce count of characters greater than str[i]
            updatecount(count, str[i]);
        }
 
        return rank;
    }
 
    // Driver code
    public static void main(String args[])
    {
        char str[] = "string".toCharArray();
        System.out.println(findRank(str));
    }
}
 
// This code has been contributed by 29AjayKumar


Python3
# A O(n) solution for finding rank of string
MAX_CHAR=256;
 
# all elements of count[] are initialized with 0
count=[0]*(MAX_CHAR + 1);
 
# A utility function to find factorial of n
def fact(n):
    return 1 if(n <= 1) else (n * fact(n - 1));
 
# Construct a count array where value at every index
# contains count of smaller characters in whole string
def populateAndIncreaseCount(str):
    for i in range(len(str)):
        count[ord(str[i])]+=1;
 
    for i in range(1,MAX_CHAR):
        count[i] += count[i - 1];
 
# Removes a character ch from count[] array
# constructed by populateAndIncreaseCount()
def updatecount(ch):
 
    for i in range(ord(ch),MAX_CHAR):
        count[i]-=1;
 
# A function to find rank of a string in all permutations
# of characters
def findRank(str):
    len1 = len(str);
    mul = fact(len1);
    rank = 1;
 
 
    # Populate the count array such that count[i]
    # contains count of characters which are present
    # in str and are smaller than i
    populateAndIncreaseCount(str);
 
    for i in range(len1):
        mul = mul//(len1 - i);
 
        # count number of chars smaller than str[i]
        # fron str[i+1] to str[len-1]
        rank += count[ord(str[i]) - 1] * mul;
 
        # Reduce count of characters greater than str[i]
        updatecount(str[i]);
 
    return rank;
 
# Driver code
str = "string";
print(findRank(str));
 
# This is code is contributed by chandan_jnu


C#
// A O(n) solution for finding rank of string
using System;
 
class GFG {
 
    static int MAX_CHAR = 256;
 
    // A utility function to find factorial of n
    static int fact(int n)
    {
        return (n <= 1) ? 1 : n * fact(n - 1);
    }
 
    // Construct a count array where value at every index
    // contains count of smaller characters in whole string
    static void populateAndIncreaseCount(int[] count, char[] str)
    {
        int i;
 
        for (i = 0; i < str.Length; ++i)
            ++count[str[i]];
 
        for (i = 1; i < MAX_CHAR; ++i)
            count[i] += count[i - 1];
    }
 
    // Removes a character ch from count[] array
    // constructed by populateAndIncreaseCount()
    static void updatecount(int[] count, char ch)
    {
        int i;
        for (i = ch; i < MAX_CHAR; ++i)
            --count[i];
    }
 
    // A function to find rank of a string in all permutations
    // of characters
    static int findRank(char[] str)
    {
        int len = str.Length;
        int mul = fact(len);
        int rank = 1, i;
 
        // all elements of count[] are initialized with 0
        int[] count = new int[MAX_CHAR];
 
        // Populate the count array such that count[i]
        // contains count of characters which are present
        // in str and are smaller than i
        populateAndIncreaseCount(count, str);
 
        for (i = 0; i < len; ++i) {
            mul /= len - i;
 
            // count number of chars smaller than str[i]
            // fron str[i+1] to str[len-1]
            rank += count[str[i] - 1] * mul;
 
            // Reduce count of characters greater than str[i]
            updatecount(count, str[i]);
        }
 
        return rank;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        char[] str = "string".ToCharArray();
        Console.WriteLine(findRank(str));
    }
}
 
/* This code contributed by PrinciRaj1992 */


PHP


输出:

598

上述解决方案的时间复杂度为O(n ^ 2)。通过创建大小为256的辅助数组,可以将时间复杂度降低到O(n)。请参见以下代码。

C++

// A O(n) solution for finding rank of string
#include 
using namespace std;
#define MAX_CHAR 256
 
// A utility function to find factorial of n
int fact(int n)
{
    return (n <= 1) ? 1 : n * fact(n - 1);
}
 
// Construct a count array where value at every index
// contains count of smaller characters in whole string
void populateAndIncreaseCount(int* count, char* str)
{
    int i;
 
    for (i = 0; str[i]; ++i)
        ++count[str[i]];
 
    for (i = 1; i < MAX_CHAR; ++i)
        count[i] += count[i - 1];
}
 
// Removes a character ch from count[] array
// constructed by populateAndIncreaseCount()
void updatecount(int* count, char ch)
{
    int i;
    for (i = ch; i < MAX_CHAR; ++i)
        --count[i];
}
 
// A function to find rank of a string in all permutations
// of characters
int findRank(char* str)
{
    int len = strlen(str);
    int mul = fact(len);
    int rank = 1, i;
 
    // all elements of count[] are initialized with 0
    int count[MAX_CHAR] = { 0 };
 
    // Populate the count array such that count[i]
    // contains count of characters which are present
    // in str and are smaller than i
    populateAndIncreaseCount(count, str);
 
    for (i = 0; i < len; ++i) {
        mul /= len - i;
 
        // count number of chars smaller than str[i]
        // fron str[i+1] to str[len-1]
        rank += count[str[i] - 1] * mul;
 
        // Reduce count of characters greater than str[i]
        updatecount(count, str[i]);
    }
 
    return rank;
}
 
// Driver program to test above function
int main()
{
    char str[] = "string";
    cout << findRank(str);
    return 0;
}
 
// This is code is contributed by rathbhupendra

C

// A O(n) solution for finding rank of string
#include 
#include 
#define MAX_CHAR 256
 
// A utility function to find factorial of n
int fact(int n)
{
    return (n <= 1) ? 1 : n * fact(n - 1);
}
 
// Construct a count array where value at every index
// contains count of smaller characters in whole string
void populateAndIncreaseCount(int* count, char* str)
{
    int i;
 
    for (i = 0; str[i]; ++i)
        ++count[str[i]];
 
    for (i = 1; i < MAX_CHAR; ++i)
        count[i] += count[i - 1];
}
 
// Removes a character ch from count[] array
// constructed by populateAndIncreaseCount()
void updatecount(int* count, char ch)
{
    int i;
    for (i = ch; i < MAX_CHAR; ++i)
        --count[i];
}
 
// A function to find rank of a string in all permutations
// of characters
int findRank(char* str)
{
    int len = strlen(str);
    int mul = fact(len);
    int rank = 1, i;
 
    // all elements of count[] are initialized with 0
    int count[MAX_CHAR] = { 0 };
 
    // Populate the count array such that count[i]
    // contains count of characters which are present
    // in str and are smaller than i
    populateAndIncreaseCount(count, str);
 
    for (i = 0; i < len; ++i) {
        mul /= len - i;
 
        // count number of chars smaller than str[i]
        // fron str[i+1] to str[len-1]
        rank += count[str[i] - 1] * mul;
 
        // Reduce count of characters greater than str[i]
        updatecount(count, str[i]);
    }
 
    return rank;
}
 
// Driver program to test above function
int main()
{
    char str[] = "string";
    printf("%d", findRank(str));
    return 0;
}

Java

// A O(n) solution for finding rank of string
 
class GFG {
 
    static int MAX_CHAR = 256;
 
    // A utility function to find factorial of n
    static int fact(int n)
    {
        return (n <= 1) ? 1 : n * fact(n - 1);
    }
 
    // Construct a count array where value at every index
    // contains count of smaller characters in whole string
    static void populateAndIncreaseCount(int[] count, char[] str)
    {
        int i;
 
        for (i = 0; i < str.length; ++i)
            ++count[str[i]];
 
        for (i = 1; i < MAX_CHAR; ++i)
            count[i] += count[i - 1];
    }
 
    // Removes a character ch from count[] array
    // constructed by populateAndIncreaseCount()
    static void updatecount(int[] count, char ch)
    {
        int i;
        for (i = ch; i < MAX_CHAR; ++i)
            --count[i];
    }
 
    // A function to find rank of a string in all permutations
    // of characters
    static int findRank(char[] str)
    {
        int len = str.length;
        int mul = fact(len);
        int rank = 1, i;
 
        // all elements of count[] are initialized with 0
        int count[] = new int[MAX_CHAR];
 
        // Populate the count array such that count[i]
        // contains count of characters which are present
        // in str and are smaller than i
        populateAndIncreaseCount(count, str);
 
        for (i = 0; i < len; ++i) {
            mul /= len - i;
 
            // count number of chars smaller than str[i]
            // fron str[i+1] to str[len-1]
            rank += count[str[i] - 1] * mul;
 
            // Reduce count of characters greater than str[i]
            updatecount(count, str[i]);
        }
 
        return rank;
    }
 
    // Driver code
    public static void main(String args[])
    {
        char str[] = "string".toCharArray();
        System.out.println(findRank(str));
    }
}
 
// This code has been contributed by 29AjayKumar

Python3

# A O(n) solution for finding rank of string
MAX_CHAR=256;
 
# all elements of count[] are initialized with 0
count=[0]*(MAX_CHAR + 1);
 
# A utility function to find factorial of n
def fact(n):
    return 1 if(n <= 1) else (n * fact(n - 1));
 
# Construct a count array where value at every index
# contains count of smaller characters in whole string
def populateAndIncreaseCount(str):
    for i in range(len(str)):
        count[ord(str[i])]+=1;
 
    for i in range(1,MAX_CHAR):
        count[i] += count[i - 1];
 
# Removes a character ch from count[] array
# constructed by populateAndIncreaseCount()
def updatecount(ch):
 
    for i in range(ord(ch),MAX_CHAR):
        count[i]-=1;
 
# A function to find rank of a string in all permutations
# of characters
def findRank(str):
    len1 = len(str);
    mul = fact(len1);
    rank = 1;
 
 
    # Populate the count array such that count[i]
    # contains count of characters which are present
    # in str and are smaller than i
    populateAndIncreaseCount(str);
 
    for i in range(len1):
        mul = mul//(len1 - i);
 
        # count number of chars smaller than str[i]
        # fron str[i+1] to str[len-1]
        rank += count[ord(str[i]) - 1] * mul;
 
        # Reduce count of characters greater than str[i]
        updatecount(str[i]);
 
    return rank;
 
# Driver code
str = "string";
print(findRank(str));
 
# This is code is contributed by chandan_jnu

C#

// A O(n) solution for finding rank of string
using System;
 
class GFG {
 
    static int MAX_CHAR = 256;
 
    // A utility function to find factorial of n
    static int fact(int n)
    {
        return (n <= 1) ? 1 : n * fact(n - 1);
    }
 
    // Construct a count array where value at every index
    // contains count of smaller characters in whole string
    static void populateAndIncreaseCount(int[] count, char[] str)
    {
        int i;
 
        for (i = 0; i < str.Length; ++i)
            ++count[str[i]];
 
        for (i = 1; i < MAX_CHAR; ++i)
            count[i] += count[i - 1];
    }
 
    // Removes a character ch from count[] array
    // constructed by populateAndIncreaseCount()
    static void updatecount(int[] count, char ch)
    {
        int i;
        for (i = ch; i < MAX_CHAR; ++i)
            --count[i];
    }
 
    // A function to find rank of a string in all permutations
    // of characters
    static int findRank(char[] str)
    {
        int len = str.Length;
        int mul = fact(len);
        int rank = 1, i;
 
        // all elements of count[] are initialized with 0
        int[] count = new int[MAX_CHAR];
 
        // Populate the count array such that count[i]
        // contains count of characters which are present
        // in str and are smaller than i
        populateAndIncreaseCount(count, str);
 
        for (i = 0; i < len; ++i) {
            mul /= len - i;
 
            // count number of chars smaller than str[i]
            // fron str[i+1] to str[len-1]
            rank += count[str[i] - 1] * mul;
 
            // Reduce count of characters greater than str[i]
            updatecount(count, str[i]);
        }
 
        return rank;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        char[] str = "string".ToCharArray();
        Console.WriteLine(findRank(str));
    }
}
 
/* This code contributed by PrinciRaj1992 */

的PHP


输出:

598