提问人:NewGreat H 提问时间:8/17/2023 更新时间:8/17/2023 访问量:26
了解 KMP 模式匹配算法中的特定细节
Understanding a Specific Detail in the KMP Pattern Matching Algorithm
问:
我有一个关于 KMP 模式匹配算法的问题。下面是用于计算数组的代码片段:next
int GetNext(char ch[], int length, int next[]) {
next[1] = 0;
int i = 1, j = 0;
while (i < length) {
if (j == 0 || ch[i] == ch[j])
next[++i] = ++j;
else
j = next[j];
}
}
我对这段代码的原理理解如下:假设我们想要确定 next[j+1
],并且我们已经知道 next[1]、next[2],...下一页[J]
.如果 next[j] =
p,则表示字符串第 j 个
字符之前最长的公共前缀和后缀的长度为 p-1
。如果字符串的第 j
个字符等于其第 p 个
字符,则 next[j+1] = p+1
。否则,我们需要考虑 next[p],如果 next[p
] =
k,我们将字符串的第 j
个字符与其第 k
个字符进行比较。
我的问题是,我们为什么不将字符串的第 j
个字符与其第 (p-1) 个
字符进行比较?我们怎么能确定将字符串的第 j 个
字符与其第 p
个字符进行比较绝对不是正确的答案?例如,请考虑以下字符串(其中 S1 中的数字是索引):
S1S2S3 S4S5S6 S7S8S9 S10 S11
使用上面的算法来计算next[11]
,我们可以确定S1S2S3S4
和S7S8S9S10
是S11
最长的公共前缀和后缀。我的问题是,我们怎么能确定这一点?我们如何确定 S1S2S3S4S5
和 S6S7S8S9S10
不是 S11
最长的通用前缀和后缀?
我想了解这个算法的细节;这个问题已经困扰了我一段时间
答:
该算法的目标是针对字符串的每个位置,确定最长前缀的长度,该前缀也是在该位置结束的字符串的后缀。
为了理智起见,让我们写一下,如果字符串的第一个字符与长度的后缀匹配,则以位置结束。我们正在尝试计算每个仓位的最大值。 微不足道。IsPrefix(a, b)
a
a
b
a
b
IsPrefix(0, b)
首先意识到,如果 ,则 .您只是匹配了一个字符。因此,我们可以通过查看从最大到最小的所有值来找到,这样两者都取了第一个,我们发现 .IsPrefix(a + 1, b + 1)
IsPrefix(a, b)
next[b + 1]
a
IsPrefix(a, b)
ch[a] == ch[b + 1]
接下来意识到,由于是最大值,因此 ,如果 ,则为第二大值。我认为这是你缺少的部分。不能有这样的值。如果这些字符与以 结尾的后缀匹配,那么它们也与以 结尾的后缀匹配,我们将得到 。next[b]
IsPrefix(next[b], b)
next[b] > 0
next[next[b]]
next[next[b]] < q < next[b]
IsPrefix(q, b)
q
b
next[b]
next[next[b]] = q
下一个:关于KMP模式匹配算法的问题
评论