学习渠道:
1.KMP入门: 831. KMP字符串 - AcWing题库 的视频讲解 及其 题解大佬的思路
2.KMP的next数组的理解:「天勤公开课」KMP算法易懂版_哔哩哔哩_bilibili
3.Z 函数(扩展 KMP) - OI Wiki (oi-wiki.org)
学习总结:
定义 : 快速的 从主串 中找到 模式串 的位置
用途:字符串匹配问题
优势 : 把n*m 的复杂度 降低为 (n+m),利用ne数组 避免了主串指针回退
算法核心:比较指针 回溯 : j=ne[j]; //这是字符串匹配最消耗时间的一部分,kmp算法就是将这里最大程度优化,即每次回溯都要回溯到最合适的位置,使得没有多余比较
求最大公共前后缀: 这样匹配了就能最少程度回溯
当 p[j+1]与前面的字符s[i]不匹配,我们只需要移动公共前缀到公共后缀的位置即可
如下图:当不匹配的时候只需要回溯到这个位置:即 最大公共前缀移动到最大公共后缀的位置即可
一.利用 最大公共前后缀求next数组:
1.我们利用最大公共前后缀求出以下需要回溯的位置:
即当一个位置不匹配时,只需回溯到最大公共前后缀+1 位即可
(因为最大公共前后缀相等,不用比较,只需要比较下一位)
2.得到表格对应关系--即next数组:
3.代码实现: 与自身进行匹配求得最大公共前后缀
二.利用已经求出的next数组进行匹配:
等级提升需要刷的题目:
a.基础:
1.模板题:831. KMP字符串 - AcWing题库
(就一个特判,不回退 一往无前!!!)
3.P2375 [NOI2014] 动物园 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
4.4189. 似乎在梦中见过的样子 - AcWing题库--(与动物园相似,但是时间卡得 很紧)
(加限制求 next数组,前后缀不重叠--解决方法while()j=ne[j]--回退到符合条件);
5.4188. 连接字符串 - AcWing题库(利用 n-ne[n] -->求最短循环节)
b.进阶:
6.二维kmp:159. 奶牛矩阵 - AcWing题库(数据范围可以 暴力枚举列,再用kmp求行的最小循环)(也可以kmp求列,再 使用转置求+kmp行)
7.160. 匹配统计 - AcWing题库(这个题目方便进一步深入了解kmp,匹配中j的含义--j -- a中以i 为结尾的后缀和 b的最长前缀匹配长度 ==j)
c.z函数kmp扩展: