1. KMP算法核心思想解析
KMP算法(Knuth-Morris-Pratt)是字符串匹配领域的经典算法,由三位计算机科学家在1977年联合发表。这个算法最精妙之处在于它通过预处理模式串构建next数组,将传统暴力匹配的O(m*n)时间复杂度优化至O(m+n)。
我在实际处理文本搜索引擎项目时,曾对比过暴力匹配和KMP的效率差异:当主串长度为10^6,模式串长度为10^3时,暴力匹配需要近百万次比较,而KMP算法仅需约两千次比较。这种效率提升在DNA序列比对、日志分析等场景下尤为关键。
1.1 为什么需要KMP算法
假设我们要在主串"ABABABC"中查找模式串"ABABC",传统暴力匹配的过程是这样的:
- 比较主串[0-4]和模式串[0-4] → 匹配失败
- 主串右移1位,比较[1-5]和[0-4] → 再次失败
- 重复这个过程直到找到匹配
这种每次失败就回退的机制造成了大量重复比较。KMP算法的核心突破在于:当发生不匹配时,不是简单地将模式串右移一位,而是利用已匹配部分的信息,智能决定移动位数。
1.2 部分匹配表(next数组)原理
next数组是KMP算法的灵魂所在,它记录了模式串各个位置的最长公共前后缀长度。以模式串"ABABC"为例:
| 索引 | 子串 | 最长公共前后缀 | next值 |
|---|---|---|---|
| 0 | A | 无 | -1 |
| 1 | AB | 无 | 0 |
| 2 | ABA | "A" | 1 |
| 3 | ABAB | "AB" | 2 |
| 4 | ABABC | 无 | 0 |
构建next数组的关键在于理解"最长公共前后缀":对于子串"ABAB",前缀集合是{"A","AB","ABA"},后缀集合是{"B","AB","BAB"},公共部分是"AB",长度为2。
关键技巧:计算next[j]时,可以利用next[j-1]的结果。如果pattern[j] == pattern[next[j
