字符串匹配KMP算法

165 阅读1分钟

参考文章

其中,原理参考文章是全网找到的最直观的视频讲解,清晰学习KMP的全过程,但未提供代码;

代码1文章未提供next表的计算代码;

代码2next表计算方法少考虑了一些情况会导致计算错误,如类似以下情况中的第四行将被计算为0,进而第五行将被计算为1;

图片来源文章1

show you code

以下代码经过有限测试无误

/*
KMP搜索
*/
func KmpSearch(haystack string, needle string) int {
   next := NextTable(needle)

   l1 := len(haystack)
   l2 := len(needle)
   i, j := 0, 0
   for i < l1 && j < l2 {
      if j == -1 || haystack[i] == needle[j] {
         i++
         j++
      } else {
         j = next[j]
      }
   }
   if j == l2 {
      return i - j
   }
   return -1
}

/*
next表计算
*/
func NextTable(needle string) []int {
   n := len(needle)
   maxL := make([]int, n)
   //计算maxL数组
   for r := 1; r < n; r++ {
      if needle[r] == needle[maxL[r-1]] {
         //本轮前缀尾部字符刚好等于上一轮maxL值对应索引元素
         maxL[r] = maxL[r-1] + 1
      } else {
         // 否则,笨办法计算本轮前缀的maxL
         maxLItem := 0
         currentPrefix := needle[:r+1]
         for i := 0; i <= maxL[r-1]; i++ {
            if currentPrefix[:i+1] == currentPrefix[r-i:] {
               maxLItem++
            } else {
               break
            }
         }
         maxL[r] = maxLItem
      }
   }
   //maxL表转next表(去尾添头)
   next := append([]int{-1}, maxL[:n-1]...)
   return next
}