在计算机科学中,字符串匹配是一个基础而重要的问题。比如你在浏览器中搜索关键词、编辑器查找文本、甚至DNA序列比对,背后都离不开高效的字符串匹配算法。
今天,我们将深入浅出地讲解 KMP算法(Knuth-Morris-Pratt 算法),并用 Go语言 实现它。无论你是编程小白还是有一定经验的开发者,都能轻松理解!

KMP算法是一种线性时间复杂度的字符串匹配算法,由 Donald Knuth、Vaughan Pratt 和 James H. Morris 于1977年提出。它的核心思想是:当发生不匹配时,利用已匹配部分的信息,避免回溯主串指针,从而提升效率。
与暴力匹配(Brute Force)相比,KMP的时间复杂度从 O(n×m) 优化到了 O(n + m),其中 n 是主串长度,m 是模式串长度。
KMP的核心在于构建一个叫做“前缀函数”(也叫 next 数组)的辅助数组。这个数组记录了模式串中每个位置的最长相等前后缀长度。
举个例子,模式串 "ABABC" 的前缀函数如下:
所以前缀函数数组为:[0, 0, 1, 2, 0]
下面我们分两步实现 KMP:1)构建前缀函数;2)执行匹配。
func buildPrefixTable(pattern string) []int { m := len(pattern) next := make([]int, m) j := 0 // 当前最长前缀后缀长度 for i := 1; i < m; i++ { // 如果当前字符不匹配,回退到上一个可能的位置 for j > 0 && pattern[i] != pattern[j] { j = next[j-1] } // 如果匹配,长度加一 if pattern[i] == pattern[j] { j++ } next[i] = j } return next}func kmpSearch(text, pattern string) int { if len(pattern) == 0 { return 0 } next := buildPrefixTable(pattern) n, m := len(text), len(pattern) j := 0 // 模式串的匹配位置 for i := 0; i < n; i++ { // 不匹配时,根据 next 数组跳转 for j > 0 && text[i] != pattern[j] { j = next[j-1] } // 匹配成功,j 向前移动 if text[i] == pattern[j] { j++ } // 完全匹配 if j == m { return i - m + 1 // 返回首次匹配位置 } } return -1 // 未找到}package mainimport "fmt"func buildPrefixTable(pattern string) []int { m := len(pattern) next := make([]int, m) j := 0 for i := 1; i < m; i++ { for j > 0 && pattern[i] != pattern[j] { j = next[j-1] } if pattern[i] == pattern[j] { j++ } next[i] = j } return next}func kmpSearch(text, pattern string) int { if len(pattern) == 0 { return 0 } next := buildPrefixTable(pattern) n, m := len(text), len(pattern) j := 0 for i := 0; i < n; i++ { for j > 0 && text[i] != pattern[j] { j = next[j-1] } if text[i] == pattern[j] { j++ } if j == m { return i - m + 1 } } return -1}func main() { text := "ABABDABACDABABCABCABC" pattern := "ABABC" pos := kmpSearch(text, pattern) if pos != -1 { fmt.Printf("模式串 '%s' 在主串中首次出现位置: %d\n", pattern, pos) } else { fmt.Println("未找到匹配") }}运行结果:
模式串 'ABABC' 在主串中首次出现位置: 9
关键在于 避免重复比较。当发生失配时,KMP通过前缀函数知道模式串可以“滑动”多少位,而不是像暴力法那样每次只移动一位。这使得整个匹配过程只需遍历主串一次。
通过本文,你已经掌握了:
KMP算法虽然初看有点抽象,但一旦理解其“利用已知信息避免重复工作”的思想,就会觉得非常巧妙。希望这篇教程能帮助你在 Go 语言学习和算法面试中更进一步!
如果你喜欢这篇文章,欢迎收藏、分享,并尝试自己动手实现一遍代码!
本文由主机测评网于2025-12-11发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025126222.html