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 }

 

如果已经理解了上述逻辑,后续对目标串进行匹配时则非常容易理解

 

posted @ 2022-06-06 17:57  学习_inging  阅读(190)  评论(0)    收藏  举报