KMP算法学习笔记
KMP算法学习笔记
KMP 算法简述
KMP 算法名字的由来
KMP 算法是对字符串匹配算法的一种简化,其同时由 D.E.Knuth J.H.Morris 和 V.R.Pratt 发现,所以被简称为 KMP 算法。
KMP 算法的用处
KMP 算法可以以 O(m + n) 的时间复杂度进行字符串匹配。
“字符串 A 是否为字符串 B 的子串?如果是的话出现在 B 的哪些位置?”该问题就是字符串匹配问题,字符串 A 被称为模式串,字符串 B 被称为主串。
——在这里,我们把模式串称为
Brute-Force 算法
Brute-Force 算法图片
ababc|abc
i----|j--
-i---|-j-
--i--|--j
-i---|j--
--i--|j--
---i-|-j-
----i|--j
---i-|j--
----i|j--
-----|j--
i 出界,程序结束
如图,当
问题来了:我们能不能利用以往的信息,让
答案是:能!
next 数组
next 数组的定义
对于模式串
next 数组的用法
比如我们考虑一组样例:
p:abcab------- t:abcacababcab首先,前四位按位匹配成功,遇到第五位不同,而这时,我们选择将
abcad向右移三位,或者可以直接理解为移动到模式串中与失配字符相同的那一位。可以简单地理解为,我们将两个已经遍历过的模式串字符重合,导致我们可以不用一位一位地移动,而是根据相同的字符来实现快速移动。p:---abcde---- t:abcacababcab
(这里加上 -,方便读者阅读)
对于模式串 abcab,其 a 移动至后面的 a 所占的位置,而它们相距
但有时不光只会有单个字符重复:
p:abcabc-------- t:abcabdababcabc当我们发现在第六位失配时,我们可以将模式串的第一二位移动到第四五位,因为它们相同
qwq.p:---abcabc----- t:abcabdababcabc
(这里忠于原文,不做其他改动)
对于模式串 abcabc,其 ab 移动至后面的 ab 所占的位置,而它们相距
next 数组的求法
暴力算法
先枚举每个
优化
举个栗子:
0123
---i
abab
问题来了,
举个例子:
0123456
abaabab
------i
若
最终代码:
void makeNext(char s[],int next[]) { int len = strlen(s); next[0]=0; //初始化 for(int i=1,k=0;i<len;i++) { while(k>0 && s[k]!=s[i]) //这个while是最关键的部分 k=next[k-1]; //等价于 k=next[next[i-1]-1] //等号右边的k起的只是下标的作用 if(s[k]==s[i]) k++; //相等就+1 next[i]=k; //赋值 } }
复杂度:
解释:对于任意 k ,因为
参考文献 (划掉)
- KMP 算法名字的由来
- KMP 算法的用处
- 字符串匹配问题
- Brute-Force 算法图片
- 自动机思路
- next 数组的用法
- next 数组的求法
- KMP 算法模板提供
- KMP 算法详解
- KMP 算法 next 数组
- bilibili视频
- 也很好
- 博客版本
- next 数组代码