使用字符串算法进行计算等级的方法

162 阅读6分钟

我们将看到,对于可以使用给定字符串的所有字符组成的单词,按词法排序的字符串的等级是什么,并使用字符串算法进行计算。

什么是字符串的词法等级?

假设我们得到一个字符串 "BAR",我们需要找到它的词法等级,那么我们可以做的是写下这个字符串的所有词法排列,然后,这个字符串 "BAR "出现的位置就是这个字符串的词法等级。

例如:"BAR "的所有排列顺序是:
ABR
ARB
BAR
BRA
RAB
RBA
我们可以看到 "BAR "出现在第三位,因此,"BAR "的排列顺序是3。

如何找到字符串的词法顺序?

一种方法是找到所有的词法排列组合,然后捕捉每个词法排列组合的位置,将给定的字符串与每个可能的排列组合相匹配,与给定字符串相匹配的位置就是字符串的词法等级。
这个解决方案的唯一问题是它不可行,因为它的时间复杂度是阶乘的。

算法

  1. 寻找字符串的lexicographic permutation。
  2. 放置一个计数器变量,对所有的排列组合进行计数。
  3. 检查要找出的字符串的lexicographic等级是否与生成的排列组合相匹配。
  4. 如果是,则打印该位置并从函数中返回。

执行

# Part of OpenGenus
global permuted_array 
permuted_array=[]
#count is our array to store the index for permutations of various length. 
global count
#Position is the variable to count the lexicographic rank of the string
position=0
#function to calculate the permutations.
def permute(remaining,test_string):
    if len(remaining)==1:
        return remaining
    for i in range(0,len(remaining)):
    #We splice the strings to get substrings which further will be reduced.
        string=remaining[0:i]+remaining[i+1:len(remaining)]
    #Recurring the spliced string to generate shorter strings.
        permuted=permute(string,test_string)
    # Base case.
        if(len(permuted)==1):
    # Concatenate the strings 
            permuted_array.append(remaining[i]+permuted)
        else:
            j=len(permuted_array[-1])#To find the length of the shortest length string in the permuted_array at any given time as modifications will be done to only those strings.
            for k in permuted_array:
                if(len(k)!=j):
                    continue
                else:
     #Concatenating the required substrings.
                    permuted_array[count[len(remaining)-1]]=remaining[i]+permuted_array[count[len(remaining)-1]]
                    if(len(test_string)==len(permuted_array[count[len(remaining)-1]])):
                        global position
                        position+=1
                    if(test_string==permuted_array[count[len(remaining)-1]]):
                        print("Lexicographic rank of the string is:",position)
                        return 0
                        
                count[len(remaining)-1]+=1
    return 0
test_string=input("Enter the string")
#sorting the input string, as only then we will be able to find out the lexicographic order using this algp, otherwise it will just print permutations irrespectove of lexicographic order.
string = ''.join(sorted(test_string))
count=[len(string)]
for i in range(0,len(string)):
    count.append(0)
permute(string,test_string)
print(permuted_array)

复杂度

时间复杂度是O(n* n!) ,因为我们的时间复杂度将是T(n)= n!+ n* n!+ (n-1)* (n-1)!+ (n-2)* (n-2)!+...1!,这将相当于T(n)= n!+ (n+1)!-1!,因为n* n!+ (n-1)* (n-1)!+ (n-2)* (n-2)!+...1! = (n+1)!-1!.因此,T(n)=n!+ (n+1)!= n!+ (n+1)* n! = n* n!+
因此,T(n)=n*n!。
空间复杂度是O(n!) ,因为我们需要一个数组来存储所有的互换。

使用计数的基本原理解决:

算法

在这个算法中,我们简单地应用了计数的基本原理,该原理简单地说,如果有n种方法做一件事,有m种方法做另一件事,那么就有n*m种方法做这两种动作。
1.假设,我们再次需要用这个算法找到 "BARE "的位置,那么我们要做的是首先对字符串进行排序,因此在排序后我们得到 "ABER"
2.我们将原始字符串的第一个字母与排序后的字母进行比较,当排序后的字母被固定在第一个位置时,我们简单地将排序后字符串的剩余字母的不同排列组合的数量相加,直到我们没有得到与原始字符串的第一个字母相同的字母
3.一旦我们得到这个字母,我们就简单地移动到原始字符串的第二个字母,并将其与排序后的字符串的所有字母进行比较,除了已经被匹配的字母,并将剩余字母的不同排列组合的数量添加到等级变量
4.我们继续这样做,直到我们没有得到与第二个字母匹配的字母。
5.同样地,我们对原始字符串的所有其他位置进行这样的操作,就可以得到该字符串的等级。

比如说:

同样,我们需要找到 "EARB "的位置,那么首先我们将对字符串进行排序,这将是 "ABER"。现在,在比较原始字符串的第一个字母和排序后的字符串时,因为它们不相等,所以我们在等级值上增加6,因为这是 "A "固定在第一个位置时可以组成的不同单词的数量,同样,在比较排序后的字符串的第二个字母和原始字符串的第一个字母时,它们仍然不相等,因此我们再次增加6的等级,但排序后的字符串的第三个字母是"E",当与原始字符串的第一个字母比较时,我们发现它们都是相等的,因此,在这里没有添加任何东西,我们将字母 "E "附加到一个存储已达到的字符串字母的数组中,现在我们到达原始字符串的第二个字母,即 "A"并再次将其与排序后的字符串的第一个字母进行比较,因为这一次它与第一个字母相等,因此,我们不增加任何等级,并再次将A追加到存储已用字母的数组中,同样,我们移动到字符串的第三个位置并开始与字符串的第一个字母进行比较,但是,由于第一个字母已经被匹配,因此,我们跳过它,移动到排序后的字符串的第二个字母,即"B",它与 "R "不匹配,因此,我们在等级上加1,因为这是由剩余字母组成的排列组合的数量,我们再次将 "R "与 "E "进行比较。但由于它已经被使用过了,所以我们跳过它,然后我们将它与最后一个字母进行比较,这个字母等于 "R",因此我们再次不增加任何等级,并将 "R "追加到存储已达成的字母的列表中。
现在,我们移动到原始字符串的最后一个字母 "B",因为我们必须跳过 "A",因为它已经被使用了,我们的最后一个字母与排序后的字符串的第二个字母相匹配,我们在等级中添加1,这将是该字符串的词汇位置。

实施:

import math
a=5
string= input("Enter the string")
sorted_string = ''.join(sorted(string))
length=len(string)
i=0
j=0
rank=0
array=[]
while(j!=length-1):
    if(string[j]!=sorted_string[i]):
        if(sorted_string[i] in array):
            i+=1
            continue
        rank+=math.factorial(length-j-1)
        i+=1
    else:
        array.append(string[j])
        j+=1
        i=0
print("Lexicographic rank of the string is:",rank+1)

复杂度:

  • 最坏情况下的时间复杂度:O(n * n)
  • 平均情况下的时间复杂度:O(n * n)
  • 最佳情况下的时间复杂度: O(n)
    空间复杂度是: O(n)

问题

找出 "CAB "的词法等级:

5

1

3

4

使用上述任何一种算法我们都可以找到它的位置。

通过OpenGenus的这篇文章,你一定对字符串的词汇学等级有了完整的了解。