KMP算法的核心在与比起暴力匹配算法,多出一个回溯表来阻止进行过度回溯。所以我们的首要工作就是建立回溯表。
建立回溯表的过程,按照我的理解方式是:通过判断子串当前指针所在位置的前n位与子串前n位字符完全匹配,便可从子串第n位字符开始继续匹配而不是将子串匹配指针直接重置到开始位置进行再次匹配。而子串中每一个字符的回溯值取决于前一个值。
代码:
func getNext(p string) []int { pSize := len(p) next := make([]int, pSize) k := -1 j := 0 next[0] = -1 for j < pSize-1 { if k == -1 || p[j] == p[k] { k++ j++ if p[j] != p[k] { next[j] = k } else { next[j] = next[k] } } else { k = next[k] } } return next } func kmp(str string, p string) int { sSize := len(str) pSize := len(p) next := getNext(p) i := 0 j := 0 for i < sSize && j < pSize { if j == -1 || str[i] == p[j] { i++ j++ } else { j = next[j] } } if j == pSize { return i - j } else { return -1 } }