如何查找字符串的可能组合总数?

时间:2017-10-28 10:03:27

标签: python string algorithm python-3.x

如何查找以特定字符开头的字符串的可能子序列的总数,说“a”并以特定字符结尾,并从给定字符串中说出'b'

例:
对于字符串'aabb',如果我们想知道如果子序列必须从字符'a'开始并以字符'b'结束,那么有多少子序列的计数,则有效的子序列可以来自(ab)由索引(0,2), (ab)提供的索引(0,3), (ab)由索引(1,2), (ab)提供,索引(1,3), (aab)由索引(0,1,2) , (aab)使用索引(0,1,3) ,(abb)使用索引{{ 1}}使用索引(0,2,3),(abb)使用索引(1,2,3)aabb本身  所以总数是9。我可以解决这个问题,因为这个字符串的长度很小但是如何解决这个问题对于一个强力不起作用的大字符串

  

注意:我们认为两个子字符串如果开始或结束则不同   在给定字符串的不同索引处。

def count(str,str1 ,str2 ):
l = len(str) 
count=0
for i in range(0, l+1):
    for j in range(i+1, l+1):
        if str[i] == str1 and str[j-1] == str2:
            count+=1
return count

2 个答案:

答案 0 :(得分:1)

在发布我的主要代码之前,我将尝试解释它是如何工作的。让源字符串为' a123b'。有效的子序列包括' 123'的所有子集。以' a'为前缀并加上' b'。所有子集的集合称为powersetitertools文档的代码显示如何使用Itertools Recipes部分中的combinations生成powerset。

# Print all subsequences of '123', prefixed with 'a' and suffixed with 'b'
from itertools import combinations

src = '123'
for i in range(len(src) + 1):
    for s in combinations(src, i):
        print('a' + ''.join(s) + 'b')

<强>输出

ab
a1b
a2b
a3b
a12b
a13b
a23b
a123b

这是一个使用该配方的蛮力解决方案。

from itertools import combinations

def count_bruteforce(src, targets):
    c0, c1 = targets
    count = 0
    for i in range(2, len(src) + 1):
        for t in combinations(src, i):
            if t[0] == c0 and t[-1] == c1:
                count += 1
    return count

可以很容易地显示the number of subsets of a set of n items is 2**n。因此,我们不是逐个生成子集,而是使用该公式来加速该过程,这就是我的count_fast函数所做的。

from itertools import combinations

def count_bruteforce(src, targets):
    c0, c1 = targets
    count = 0
    for i in range(2, len(src) + 1):
        for t in combinations(src, i):
            if t[0] == c0 and t[-1] == c1:
                count += 1
    return count

def count_fast(src, targets):
    c0, c1 = targets
    # Find indices of the target chars
    idx = {c: [] for c in targets}
    for i, c in enumerate(src):
        if c in targets:
            idx[c].append(i)

    idx0, idx1 = idx[c0], idx[c1]
    count = 0
    for u in idx0:
        for v in idx1:
            if v < u:
                continue
            # Calculate the number of valid subsequences
            # which start at u+1 and end at v-1. 
            n = v - u - 1
            count += 2 ** n
    return count

# Test

funcs = (
    count_bruteforce,
    count_fast,
)

targets = 'ab'

data = (
    'ab', 'aabb', 'a123b', 'aacbb', 'aabbb', 
    'zababcaabb', 'aabbaaabbb',
)

for src in data:
    print(src)
    for f in funcs:
        print(f.__name__, f(src, targets))
    print()

<强>输出

ab
count_bruteforce 1
count_fast 1

aabb
count_bruteforce 9
count_fast 9

a123b
count_bruteforce 8
count_fast 8

aacbb
count_bruteforce 18
count_fast 18

aabbb
count_bruteforce 21
count_fast 21

zababcaabb
count_bruteforce 255
count_fast 255

aabbaaabbb
count_bruteforce 730
count_fast 730

可能可以通过在正确的位置启动内循环而不是使用continue来跳过不需要的索引来提高速度。

答案 1 :(得分:0)

简单,它应该是两个幂的字母数。即,n^2

Python实现只是n_substrings = n ** 2