39-KMP 执行过程
建议去看原文,下文只摘出了KMP过程且做了少许修改;https://www.cnblogs.com/SYCstudio/p/7194315.html
1. 引入#
- 首先我们来看一个例子,现在有两个字符串 A 和 B,问你在 A 中是否有 B,有几个?为了方便叙述,我们先给定两个字符串的值
- A = "abcaabababaa"
- B = "abab"
- 那么普通的匹配是怎么操作的呢?当然就是一位一位地比啦。(下面用蓝色表示已经匹配,黑色表示匹配失败)
- 但是我们发现这样匹配很浪费!为什么这么说呢,我们看到第 4 步:
- 在第 4 步的时候,我们发现第 3 位上 c 与 a 不匹配,然后第 5 步的时候我们把 B 串向后移 1 位,再从第 1 个开始匹配
- 这里就有一个对已知信息很大的浪费,因为根据前面的匹配结果,我们知道 B 串的前 2 位是 ab,所以不管怎么移,都是不能和 b 匹配的,所以应该直接跳过对 A 串第 2 位的匹配,对于 A 串的第 3 位也是同理
- 再举一个例子
2. KMP 算法#
2.1 先摆出 2 个概念#
前缀:指的是字符串的子串中从原串最前面开始的子串,如 abcdef 的前缀有:a,ab,abc,abcd,abcde
后缀:指的是字符串的子串中在原串结尾处结尾的子串,如 abcdef 的后缀有:f,ef,def,cdef,bcdef
- KMP算法引入了一个 F 数组(在很多文章中会称为next,但笔者更习惯用F,这更方便表达),F[i] 表示的是前 i 的字符组成的这个子串最长的相同前缀后缀的长度!
- 怎么理解呢?例如字符串
aababaaba
的相同前缀后缀有a
和aaba
,那么其中最长的就是aaba
- 那么,为了防止读者在接下来的内容中感到和笔者之前学习时同样的困惑,在这里先对下文做一些说明和约定
- 本文中,所有的字符串从 0 开始编号
- 本文中,F数组(即其他文章中的 next),F[i] 表示 0 ~ i 的字符串的最长相同前缀后缀的长度
2.2 F 数组的运用#
- 那么现在假设我们已经得到了 F 的所有值,我们如何利用 F数组 求解呢?
- 我们还是先给出一个例子(笔者用了好长时间才构造出这一个比较典型的例子啊)
- A = "abaabaabbabaaabaabbabaab"
- B = "abaabbabaab"
- 当然读者可以通过手动模拟得出只有一个地方匹配
- abaabaabbabaaabaabbabaab
- 那么我们根据手动模拟,同样可以计算出各个 F 的值
- 我们再用 i 表示当前 A 串要匹配的位置(即还未匹配),j 表示当前 B 串匹配的位置(同样也是还未匹配),补充一下,若 i>0 则说明 i-1 是已经匹配的啦( j 同理)
2.3 举例说明匹配过程#
- 首先我们还是从 0 开始匹配:
- 此时,我们发现,A 的第 5 位和 B 的第 5 位不匹配(注意从0开始编号),此时i=5,j=5,那么我们看 F[j-1] 的值:
F[5-1] = 2;
- 这说明我们接下来的匹配只要从 B 串第 2 位开始(也就是第 3 个字符)匹配,因为前两位已经是匹配的啦(想象成先前已经移动 {B 串}, 让它和 { A 串的前 i - 1 个字符构成的串} 的后缀对齐了),具体请看图:
- 然后再接着匹配:
- 我们又发现, A 串的第 13 位和 B 串的第 10 位不匹配,此时 i=13,j=10,那么我们看 F[j-1] 的值:
F[10-1] = 4
- 这说明 B 串的 0~3 位是与当前 (i-4)~(i-1) 是匹配的,我们就不需要重新再匹配这部分了,把 B 串向后移,从B串的第 4 位开始匹配:
- 这时我们发现 A 串的第 13 位和 B 串的第 4 位依然不匹配
- 此时i=13,j=4,那么我们看 F[j-1] 的值:
F[4-1] = 1
- 这说明 B 串的第 0 位是与当前 i-1 位匹配的,所以我们直接从 B 串的第 1 位继续匹配:
- 但此时 B 串的第 1 位与 A 串的第 13 位依然不匹配
- 此时,i=13,j=1,所以我们看一看 F[j-1] 的值:
F[1-1] = 0
- 好吧,这说明已经没有相同的前后缀了,直接把 B 串向后移 1 位,直到发现 B 串的第 0 位与 A 串的第 i 位可以匹配(在这个例子中,i = 13)
- 再重复上面的匹配过程,我们发现,匹配成功了!
这就是 KMP 算法的全过程:
另外强调一点,当我们将 B 串向后移的过程其实就是 i++ ;而当我们不动 B,而是匹配的时候,就是i++,j++,这在后面的代码中会出现,这里先做一个说明。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)