【问题标题】:python3 how to find the largest prefix of a string of bytes that is a substring of anotherpython3如何找到一个字节字符串的最大前缀,它是另一个字节的子字符串
【发布时间】:2017-11-06 06:24:20
【问题描述】:

我需要找到一个字节对象 s1 的最大前缀(从开头开始的字节串),它是另一个字节对象 s2 的子字符串,并返回 s2 中的起始位置和长度。在这种情况下,s2 也恰好与 s1 重叠。

最佳结果是距离 s2 结尾最近的最长前缀。

我尝试使用下面的 bytes.rfind 方法来实现这一点。

注意:这是试图在字节对象src 中从索引index 开始查找最大前缀,该前缀在src 中较早出现在index 之前的最大maxOffset 字节内。因此,s1 是src[index:],s2 是src[index-maxOffset:index+maxLength-1]maxLength 是我有兴趣搜索的前缀的最大长度。

def crl(index, src, maxOffset, maxLength):
    """
    Returns starting position in source before index from where the max runlength is detected.
    """
    src_size = len(src)
    if index > src_size:
        return (-1, 0)
    if (index+maxLength) > src_size:
        maxLength = src_size - index
    startPos = max(0, index-maxOffset)
    endPos = index+maxLength-1
    l = maxLength

    while l>1:
        if src[index:index+l] in src[startPos:index+l-1]:
            p = src.rfind(src[index:index+l], startPos, index+l-1)
            return (p,l)
        l -= 1
    return (-1, 0)

由于之前的实现非常慢,我也尝试如下手动编码

def ocrl(index, src, maxOffset, maxLength):
    """
    Returns starting position in source before index from where the max runlength is detected.
    """
    size = len(src)
    if index>=size:
        return (-1, 0)
    startPos = index - 1 # max(0, index-maxOffset)
    stopPos = max(0, index-maxOffset)
    runs = {}
    while(startPos >= stopPos):
        currRun = 0
        pos = startPos
        while src[pos] == src[index+currRun]:
            currRun += 1
            pos += 1
            if currRun == maxLength:
                return (startPos, maxLength) #found best possible run
            if (pos >= size) or ((index+currRun) >= size):
                break
        if (currRun > 0) and (currRun not in runs.keys()):
            runs[currRun] = startPos
        startPos -= 1

    if not runs:
        return (-1, 0)
    else:
        # Return the index from where the longest run was found
        return (runs[max(runs.keys())], max(runs.keys()))

虽然第二次实现速度更快,但它仍然很慢,而且我认为效率低下。我怎样才能使它更高效并运行得更快?

【问题讨论】:

  • os.path.commonprefix 能让你的函数更快吗?
  • 如果字符串的字节值超出可打印的 ascii 范围,os.path.commonprefix 是否重要?它会像'.'这样对待字符吗?或 '/' 以特殊方式?
  • 我没有看到任何 in the sources 会在这些问题上给您带来任何麻烦。

标签: python string algorithm search


【解决方案1】:

在我看来,您可以使用修改后的 Knuth-Morris-Pratt 字符串搜索算法,尽可能匹配子字符串并提醒找到的最长匹配项。

我不确定向后而不是向前工作是否有好处,因为当您找到匹配项时,您需要继续搜索更长的匹配项(除非您匹配了整个字符串)。

【讨论】:

  • 向后的原因是probem的更大上下文-目标是检测最接近s1开头的最长前缀。如果相同的前缀在 s2 中出现两次,那么第一次出现的那一秒就是正确的答案。
  • @MadhurikoushikèKoushik:我知道。我认为这不会产生真正的影响,因为在大多数情况下,无论如何您都必须继续搜索。
【解决方案2】:

为第二个字符串构建 suffix array 并在该数组中搜索第一个字符串,选择最长公共前缀的最后一个索引

【讨论】:

  • 谢谢@MBo。很快就会尝试。我的代表显然太低了,无法为您的答案 +1。
猜你喜欢
  • 2013-09-06
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 2011-02-09
  • 2019-05-11
  • 1970-01-01
相关资源
最近更新 更多