KMP算法主要是用于字符串匹配,返回模式串出现的第一个位置。
最关键的步骤在于得出next数组,求出next数组那么kmp就差不多完成了。next数组的实现方式有很多,这里使用没经过处理的next。
以leetcode 28题为例。
func strStr(haystack string, needle string) int {
next := getNext(needle)
j := 0
i := 0
for i < len(haystack) {
if haystack[i] == needle[j] {
i++
j++
} else if j > 0 {
//回退的时候是要回退j-1而不是j
j = next[j-1]
} else {
// j回退到了0位置,那么就移动原字符串的位置重新开始匹配
i++
}
// 此时匹配完成
if j == len(needle) {
return i - j
}
}
return -1
}
func getNext(needle string) []int {
n := len(needle)
next := make([]int, n)
//前缀结束的位置
i := 0
//后缀结束的位置
j := 1
for ; j < n; j++ {
//这里当i>0的时候才可以进行回退
//最关键的是要使用for而不是if,因为要不停的回退直到相等或者i为0
for i > 0 && needle[i] != needle[j] {
//这里是回退i-1的位置
i = next[i-1]
}
if needle[i] == needle[j] {
//i代表了前缀结束的位置,也是相等前后缀的长度
i++
next[j] = i
}
}
return next
}