KMP
和Z
算法是众所周知的字符串搜索算法,
KMP
算法处理通过KMP失败函数查找模式,该函数定义为(pat
是搜索模式)
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的前缀。
现在问题是我们可以通过使用Z
算法来实现KMP
函数吗?
我要搜索的是lps
数组中的一些修改,这些修改会导致与Z[i]
数组相同的结果。
答案 0 :(得分:3)
注意:算法错误
for i in range(0, len(s)):
if lps[i] != 0:
Z[i - lps[i] + 1] = lps[i]
之后在Z[i]
中将是后缀的最大长度,从位置i
开始,也是字符串的前缀。
修改强>
正如nikhil_vyas所说,提出的算法无法解决您的问题。它实际上做的是用最长的后缀和其他一些部分填充Z
数组。这种不完整的数组基本上可以帮助你解决几个“找到字符串中最长的东西”的问题,但它没有回答你的问题。
重建具有Z
数组的lps
数组的最简单方法是构建字符串,对应于lps
数组,然后构建Z
数组为那个字符串。但我不确定它是否适合您对“lps
数组中的某些修改”的定义。
答案 1 :(得分:1)
我认为这样做会。
Z = [0] * len(lps) # initialize most to 0
iterator = enumerate(zip(lps, lps[1:]), start=1)
for i, (prev, cur) in iterator: # step through adjacent pairs
if cur <= prev: # suffix stopped growing
Z[i - prev] = prev # Mark this suffix at its beginning.
# end of loop
# 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
样品:
lps = [0,0,0,1,2] #=> [0,0,0,2,0]
lps = [0,0,1,2,1,2] #=> [0,0,2,0,2,0]
答案 2 :(得分:0)
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) `