KMP具体讲解就不说了,我讲得肯定没有网上的各位大神好,这里我找到一篇讲得比较好的,通俗易懂的。可以参考下:http://wiki.jikexueyuan.com/project/kmp-algorithm/define.html
直接上代码,难懂的地方我稍微注释了下。
//传统next数组
func getNext(p string) []int {
pLen := len(p)
next := make([]int, pLen, pLen)
next[0] = -1
next[1] = 0
i := 0
j := 1
for j < pLen-1 { //因为next[pLen-1]由s[i] == s[pLen-2]算出
if i == -1 || p[i] == p[j] { //-1代表了起始位不匹配,i=0,s[0]!=s[j]=>i=next[0]=-1
i++
j++
next[j] = i
} else {
i = next[i]
}
}
return next
}
//优化next数组
func getNextOptimize(p string) []int {
pLen := len(p)
next := make([]int, pLen, pLen)
next[0] = -1
next[1] = 0
i := 0
j := 1
for j < pLen-1 { //因为next[pLen-1]由s[i] == s[pLen-2]算出
if i == -1 || p[i] == p[j] { //-1代表了起始位不匹配,i=0,s[0]!=s[j]=>i=next[0]=-1
i++
j++
if p[i] != p[j] { //因为出现在j位置不匹配的话会跳到next[j]=i位置去匹配,p[i] == p[j]肯定又是不匹配(优化核心点)
next[j] = i
} else {
next[j] = next[i]
}
} else {
i = next[i]
}
}
return next
}
/*为何不匹配时i=next[i]?
__________________i----____________j
****next[i]___****i----________****j
由next[j] = i知道_____和_____相等
由next[i]知道****相等
所以不匹配时i先回溯到next[i]位置
*/
func KmpSearch(s, p string) int {
i, j := 0, 0
pLen := len(p)
sLen := len(s)
next := getNext(p)
for i < sLen && j < pLen {
if j == -1 || s[i] == p[j] { //s[i]!=s[0]=>j=next[0]=-1,第0位不匹配所以i++,j++;j=0
i++
j++
} else {
j = next[j]
}
}
if j == pLen {
return i - j
} else {
return -1
}
}