Go语言实现kmp算法(一)
kmp算法分为两部分,第一部分为next数组的获取,第二部分为使用next数组进行匹配,两部分采用的思路大体相同。
该算法有多种方式实现,此处介绍移动的方式实现,还有教科书上的手算方法实现,即计算最大前后子串长度,将next数组向后一位,首位置为-1,则匹配过程中移动距离等于 = 当前index - index处子串长度。
本博客使用直接移动子串的方式,对第一部分进行解释,整体思路为:当匹配模式串p,在发生不匹配的情况下,下一次该匹配哪一位。
next数组的获取思路已经写在了注释中,代码如下:
// Go语言 func getNext(p string) []int { n := len(p) next := make([]int, n) i := 0 k := -1 next[0] = k // 将第一位赋值为 -1 for { // 此处控制 i++ 时不超出字符串范围 if i >= n-1 { break } // 刚开始、回溯到了-1 或 正在进行匹配中的子串匹配了 if k == -1 || p[k] == p[i] { k++ i++ // 该 if 情况表示,匹配中的子串在下一处匹配时不匹配了。在对目标串进行查找时,需要将当前比较的位置对准模式串的第k位, // 因为上面的k++,已经将该位移动到下一位置了,而前面的位置都是匹配的 if p[i] != p[k] { next[i] = k // 当模式串的前后子串在下一处任然是匹配的。该处移动信息:如果在对目标串匹配的过程中此处发生了不匹配,就可以利用已知匹配的信息,依照已知 k 处发生过的
// 不匹配的情况进行移动,即next[k] } else { next[i] = next[k] } // 此处可以在循环体内进行回溯,目的是将k回溯到-1或能让p[k]与p[i]发生匹配的位置继续匹配。由于i++的情况只发生在k==-1或发生子串匹配的情况,
// 所以此处就巧妙的变成了一个回溯逻辑 } else { // 当第k位发生不匹配,跳至第next[k]位 k = next[k] } } return next }
如果已经理解了上述逻辑,后续对目标串进行匹配时则非常容易理解
浙公网安备 33010602011771号