给你一个文本串S,一个非空模板串T,问S在T中出现了多少次,时间复杂度要求O(n*m),如果我们用暴力法解决的话,会因为超时失败。
KMP算法的核心在于构造next数组,当我们构造出next数组,问题就会迎刃而解,所谓next数组,就是文本串S每一个位置前的最长公共前缀的结束的下标,这样说可能还是有点晦涩,即数组i位置的值即为i位置之前的字符串头尾相同的字符的数量。
首先构造next数组,如图
func MakeNext(s string) []int {
next := make([]int, len(s)+1)
next[0] = -1
i, j := 0, -1
for i < len(s) {
if j == -1 || s[i] == s[j] {
j++
i++
next[i] = j
} else {
j = next[j]
}
}
return next
}
构造完成之后,我们就可以直接使用这个数组来快速的进行匹配算法。
func kmp(S string, T string) int {
// write code here
next := MakeNext(S)
result := 0
for i, j := 0, 0; i < len(T); {
if j == -1 || S[j] == T[i] {
i++
j++
} else {
j = next[j]
}
if j == len(S) {
j = next[j]
result++
}
}
return result
}
算上构造next数组的时间,最后算下来的时间复杂度为O(N*M),符合条件。