在Python中搜索子字符串字符的排列

3

我试图从一行文本中提取一个字符串及其所有字符的排列组合的出现次数。

例如,我需要从以下字符串s中提取字符串t = 'ABC'及其所有排列组合:'ABC'、'CAB'、'BCA'、'BAC'、'CBA'。

s = 'ABCXABCXXACXXBACXXBCA'

结果为:ABCABCBACBCA

字符串t可以是任意长度,包含[A-Z][a-z][0-9]中的任意字符。

是否有办法在Python中使用正则表达式获得结果?

我知道我可以建立一个包含所有排列的列表,然后对列表中的所有项目进行单独搜索,但我想知道正则表达式是否可以提供更紧凑和更快速的结果。


1
我认为正则表达式无法解决这个问题。你可能需要使用滑动窗口算法来查找,最坏情况下的时间复杂度为O(n*a),其中n是字符串的长度,a是字母表的大小(在你的情况下,a=26+26+10=62)。 - nhahtdh
字符串 t 中是否包含重复字符? - PM 2Ring
2个回答

2

一个正则表达式的解决方案:

([ABC])(?!\1)([ABC])(?!\1)(?!\2)[ABC]

2

让我勾画一个解决问题的算法。这不是使用正则表达式解决的问题。

该解决方案维护一个滑动窗口,并检查窗口中字符的频率与t的频率是否相同。

以下是该算法的伪代码:

function searchPermutation(inpStr, t):
    // You may want to check t against the regex ^[A-Za-z0-9]+$ here

    // Do a frequency counting of character in t
    // For example, t = 'aABBCCC'
    // Then freq = { 'A': 1, 'B': 2, 'C': 3, 'a': 1 }
    freq = frequency(t)

    // Create an empty dict
    window = {}
    // Number of characters in window
    count = 0
    // List of matches
    result = []

    for (i = 0; i < inpStr.length; i++):
        // If the current character is a character in t
        if inpStr[i] in freq:
            // Add the character at current position
            window[inpStr[i]]++

            // If number of character in window is equal to length of t
            if count == t.length:
                // Remove the character at the end of the window
                window[inpStr[i - t.length]]--
                // The count is kept the same here
            else: // Otherwise, increase the count
                count++

            // If all frequencies in window is the same as freq
            if count == t.length and window == freq:
                // Add to the result a match at (i - t.length + 1, i + 1)
                // We can retrieve the string later with substring
                result.append((i - t.length + 1, i + 1))

                // Reset the window and count (prevent overlapping match)
                // Remove the 2 line below if you want to include overlapping match
                window = {}
                count = 0
        else: // If current character not in t
            // Reset the window and count
            window = {}
            count = 0

    return result

这应该可以解决任何 t 的一般问题。

谢谢。经过几次正则表达式的实验,我认为最好的方法是使用滑动窗口。 - cygnusxr1
@cygnusxr1:如果上述算法中有任何错误(例如偏移1),请随时评论。我没有编写任何实际代码来测试这个算法,但是这个想法应该是正确的。 - nhahtdh
回顾一下,window == freq 检查是很耗费时间的。我们可以保留一个映射(字符到索引列表)来找出要跳转到的最后一个索引,因为我们在循环的每一步中都检查添加的字符是否超过了限制。 - nhahtdh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接