【问题标题】:Relation between KMP algorithm and Z algorithmKMP算法与Z算法的关系
【发布时间】:2013-08-29 21:34:02
【问题描述】:

KMP 和 Z 算法是众所周知的字符串搜索算法,

KMP 算法通过定义为(pat 是搜索模式)的 KMP 失效函数来查找模式

lps[i] = pat[0..i] 的最长专有前缀,它也是 pat[0..i] 的后缀。

例如对于string "abcab",它将是[0, 0, 0, 1, 2]

Z 算法使用 z 函数定义为:

给定一个长度为 n 的字符串 S,Z 算法生成一个数组 Z,其中 Z[i] 是从 pat[i] 开始的最长子字符串的长度,它也是 pat 的前缀。

现在的问题是我们可以通过KMP算法实现Z功能吗? 我正在寻找的是对 lps 数组的一些修改,这些修改会导致与 Z[i] 数组相同的结果。

【问题讨论】:

    标签: string algorithm search


    【解决方案1】:

    注意:算法错误

    for i in range(0, len(s)):
        if lps[i] != 0:
            Z[i - lps[i] + 1] = lps[i]
    

    在Z[i]之后将是后缀的最大长度,从位置i开始,也是字符串的前缀。

    编辑

    正如 nikhil_vyas 所指出的,所提出的算法并不能解决您的问题。它实际上做的是用最长的后缀和其他一些后缀部分填充Z 数组。这样的不完整数组基本上可以帮你解决几个“在字符串中找最长的东西”的问题,但它并不能回答你的问题。

    我想到重建具有lps 数组的Z 数组的最简单方法是构建字符串,对应于lps 数组,然后为该字符串构建Z 数组。但我不确定它是否适合您对“lps 数组中的一些修改”的定义。

    【讨论】:

    • 为什么这会填充所有索引的 Z 数组?
    • 嘿@Mikhail,你可能想看看我的解决方案。
    【解决方案2】:

    我认为这样就可以了。

    def Z(lps):
        # First assume that we always need to restart when we find a mismatch.
        Z = [0] * len(lps)
    
        # Step through adjacent pairs.
        itr = enumerate(zip(lps, lps[1:]), start=1)
        for i, (prev, cur) in itr:
            if cur <= prev: # suffix stopped growing
                Z[i - prev] = prev # Mark this suffix at its beginning.
    
        # Ending the string is also a way to stop growing the suffix.
        if cur > 0: # if we were still growing a suffix
            # At end of loop, cur is the new prev, and i+1 is the new i.
            # (i == len(lps) - 1, cur == lps[-1])
            Z[i+1 - cur] = cur
    
        return Z
    

    样品:

    Z([0,0,0,1,2]) #=> [0,0,0,2,0]
    Z([0,0,1,2,1,2]) #=> [0,0,2,0,2,0]
    

    【讨论】:

      【解决方案3】:

      Mikhail Melnik 的解决方案可能不会为像“aaaaa”这样的字符串中的所有索引计算 Z,我们需要额外的迭代来填充在第一次迭代中留空的索引。

      for i in range(0, len(s)):
          Z[i - lps[i] + 1] = lps[i]
      for i in range(0, len(s)):
          Z[i] = max(Z[i], Z[i - 1] - 1)                     `
      

      【讨论】:

      • 很遗憾你的修改也是错误的。考虑 lps=[0,0,1,2] 的字符串“abab”。右 Z 数组将是 [0,0,2,0],您的算法将产生 [0,0,2,1]。
      • 另请注意,我的初始代码中有一个错误。如果 lps 数组的最后一个元素为 0,则会出现“index out of bounds”异常。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-11
      • 2021-07-21
      • 1970-01-01
      相关资源
      最近更新 更多