查找一个字符串在另一个字符串中的所有排列

Find all permutation of a string in another string

我有一个字符串,例如:string1 = 'abcdbcabdcabb'。 我还有另一个字符串,例如:string2 = 'cab'

我需要计算 string2string1 中的所有排列。

目前我正在将 string2 的所有排列添加到列表中, 然后通过 index+string.size 迭代抛出 string1 并检查 如果 string1 的子字符串包含在排列列表中

我确定有更好的优化方法。

您可以为此使用正则表达式。


def lst_permutation(text):
    from itertools import permutations
    lst_p=[]
    for i in permutations(text):
        lst_p.append(''.join(i))
    return lst_p

def total_permutation(string1,string2):
    import re
    total=0
    for i in lst_permutation(string2):
        res=re.findall(string2,string1)
        total += len(res)
    return total


string1 = 'abcdbcabdcabb'
string2 = 'cab'
print(total_permutation(string1,string2))
#12

您可以在此处使用 string.count() 方法。请参阅下面的一些解决方法:

import itertools
perms=[''.join(i) for i in itertools.permutations(string2)]

res=0

for i in perms:
    res+= string1.count(i)

print(res)
# 4

在我看来你不需要DP,而是滑动window技术。 string2 的排列是长度完全相同且字符分布相同的字符串。在您的 string2 示例中,排列是。具有以下字符分布的长度为 3 的字符串:{a:1,b:1,c:1}.

所以你可以写一个脚本,考虑一个 window 大小为 N(string2 的大小),从 string1(index=0) 开始。如果你当前的 window 具有完全相同的字符分布,你接受它作为一个排列,如果不是你不计算它,你继续 index+1.

每次滑动不重新计算字符分布的技巧window,可以得到一个字符字典,统计最开始的字符window,然后滑动window 向右一位,您将删除字符减一,将添加字符增加一。

代码应该是这样的,你需要验证它的边缘情况:

def get_permut(string1,string2):
    N =len(string2)
    M = len(string1)

    if M < N:
        return 0


    valid_dist = dict()
    for ch in string2:
        valid_dist.setdefault(ch,0)
        valid_dist[ch]+=1
    
    current_dist=dict()
    for ch in string1[:N]:
        current_dist.setdefault(ch,0)
        current_dist[ch]+=1
    
    ct=0
    for i in range(M-N):
        if current_dist == valid_dist:
            ct+=1
        current_dist[i]-=1
        current_dist.setdefault(i+1,0)
        current_dist[i+1]+=1
        if current_dist[i]==0:
            del current_dist[i]
    
    return ct
        

这是使用正则表达式执行此操作的愚蠢方法(实际上不要这样做)。

对搜索文本中的每个字母使用非捕获组,然后期望每个捕获组中的一个出现在输出中:

import re

string1 = 'abcdbcabdcabb'
string2 = r'(?:c()|a()|b()){3}'


pos = 0
r = re.compile(string2)
while m := r.search(string1, pos=pos):
    print(m.group())
    pos = m.start() + 1
abc
bca
cab
cab

也可以动态生成

import re

string1 = 'abcdbcabdcabb'
string2 = 'cab'

before = "|".join([f"{l}()" for l in string2])
matches = "".join([f"\{i + 1}" for i in range(len(string2))])
r = re.compile(f"(?:{before}){{{len(string2)}}}{matches}")

pos = 0
while m := r.search(string1, pos=pos):
    print(m.group())
    pos = m.start() + 1