KMP故障函数计算

时间:2013-04-20 21:49:16

标签: string-matching knuth knuth-morris-pratt

我的教授解决了kmp失败函数如下:

index  1 2 3 4 5 6 7 8 9
string a a b a a b a b b
ff     0 1 2 1 2 3 4 5 1

从我在网上查看的其他文本中,我发现它可能是错的,我再次向他证实,他告诉我他是绝对正确的。有人可以向我解释为什么他会以简单的一步一步的方式认为这是对还是错?感谢

2 个答案:

答案 0 :(得分:19)

据我了解算法,您的示例的失败函数应如下:

1 2 3 4 5 6 7 8 9
a a b b a b b b

0 1 0 1 2 3 4 0 0

f - 失败函数(根据定义,这是字符串的最长前缀的长度,也是后缀)

这是我如何逐步建立的:

f(a)= 0(一个字母总是= 0)

f(aa)= 1(一个字母'a'既是前缀又是后缀)

f(aab)= 0(没有相同的后缀和前缀:a!= b,aa!= ab)

f(aaba)= 1('a'在开头和结尾都是相同的,但如果你拿2个字母,它们将不相等:aa!= ba)

f(aabaa)= 2(你可以拿'aa'而不是更多:aab!= baa)

f(aabaab)= 3(你可以拿'aab')

f(aabaaba)= 4(你可以带'aaba')

f(aabaabab)= 0('a'!='b','aa'!='ab'等等,它不能= 5,所以'aabaa'!='aabab')

f(aabaababb)= 0(同样的情况)

答案 1 :(得分:0)

由于@user1041889 感到困惑(也让我感到困惑),我将在这里说明 Z 函数和失败函数之间的区别。

失败函数,π[i]

<块引用>

是和索引到字符串最长前缀长度的映射,也是后缀

但那可以说是中文,所以我将把它简化一下,以便真正理解我在说什么:

<块引用>

感兴趣的字符串开头的最长子字符串有多大,即等于以索引i结尾的子字符串

或等效地:

<块引用>

在索引i处与感兴趣的字符串的开头匹配的最大子字符串的长度是多少

所以在你的例子中:

index  1 2 3 4 5 6 7 8 9
string a a b a a b a b b
ff     0 1 0 1 2 3 4 0 0

我们观察到 π[6] = 3,那么在索引 6 处结束、长度为 3 的子串是什么? aab

有趣的是我们以前是如何看到的!

让我们检查一下它是否确实是最大的:baab != aab。是的!

注意这意味着失效函数总是均匀增长。

Z 算法并非如此。

[保存草稿以稍后继续]