参考文章
其中,原理参考文章是全网找到的最直观的视频讲解,清晰学习KMP的全过程,但未提供代码;
代码1文章未提供next表的计算代码;
代码2next表计算方法少考虑了一些情况会导致计算错误,如类似以下情况中的第四行将被计算为0,进而第五行将被计算为1;
show you code
以下代码经过有限测试无误
/*
KMP搜索
*/
func KmpSearch(haystack string, needle string) int {
next := NextTable(needle)
l1 := len(haystack)
l2 := len(needle)
i, j := 0, 0
for i < l1 && j < l2 {
if j == -1 || haystack[i] == needle[j] {
i++
j++
} else {
j = next[j]
}
}
if j == l2 {
return i - j
}
return -1
}
/*
next表计算
*/
func NextTable(needle string) []int {
n := len(needle)
maxL := make([]int, n)
//计算maxL数组
for r := 1; r < n; r++ {
if needle[r] == needle[maxL[r-1]] {
//本轮前缀尾部字符刚好等于上一轮maxL值对应索引元素
maxL[r] = maxL[r-1] + 1
} else {
// 否则,笨办法计算本轮前缀的maxL
maxLItem := 0
currentPrefix := needle[:r+1]
for i := 0; i <= maxL[r-1]; i++ {
if currentPrefix[:i+1] == currentPrefix[r-i:] {
maxLItem++
} else {
break
}
}
maxL[r] = maxLItem
}
}
//maxL表转next表(去尾添头)
next := append([]int{-1}, maxL[:n-1]...)
return next
}