LeetCode KMP 算法
创始人
2025-05-30 09:17:58

可以参考

https://www.bilibili.com/video/BV1AY4y157yL/

kmp 主要做的就是子串匹配,类似C程序的 strstr() 函数

记录一下,也防止我自己忘记

传统暴力求解算法是

源串 aaaabbbb
子串 ab先 
aaaabbbb
ab然后发现第二个字符a和b不匹配,然后子串又从第一个位置 a 开始匹配
aaaabbbbab再后面就是
aaaabbbbab

效率不高

kmp的算法出现,就是为了解决这个问题

kmp是由三位大佬发现的,他们三人的名字首字母分别就是K、M、P

比如在这个场景下

源串 ssssssssa
子串 sssa(下面暴力求解)
先 (子串从 0 位置匹配,并且匹配到最后一个字符才发现不对,白搞)
ssssssssasssa其次 (子串从 0 位置匹配,并且匹配到最后一个字符才发现不对,白搞)
ssssssssasssa再后面就是 (子串从 0 位置匹配,并且匹配到最后一个字符才发现不对,白搞)
ssssssssasssa

有没有一种办法就是少做无用功

先 (a和c不匹配)
ssssssssa
sssa其次,(子串从 2 位置匹配)
ssssssssasssa然后,(子串从 2 位置匹配)
ssssssssasssa.......最后
然后,(子串从 2 位置匹配),匹配成功
ssssssssasssa

从 2 位置匹配,显然提高了匹配速度

但是 2 位置是怎么知道的呢,kmp 算法中就是先计算一个数组叫做 next,这个next计算只需要子串,然后next的作用是记录子串回溯的位置,当源串和子串不匹配时,不像上面那样老是回溯0

回溯的位置就是最长前缀的位置

比如

子串      abcabcd
next数组  ...1230
解释
1 是因为 a=a
2 是因为前面已经有匹配字符 a=a 了,那么 现在刚好 b=b,就最长前缀就等于 1 的基础上加 1 等于 2
3 是因为前面已经有匹配字符 a=a b=b 了,那么 现在刚好 c=c,就最长前缀就等于 2 的基础上加 1 等于 3
0 是因为d没有最长前缀为啥next是基于前缀,因为比如我都匹配到最后一位d不相等了,由于前面有相似的前缀
源串 abcabcaeee
子串 abcabcd那么下一步就是 (e和b比,就是因为前缀一样,才敢让子串匹配位置不从0开始,因为前面有相似的结构)
源串 abcabcaeee
子串    abcabcd

下面计算next函数的解释

子串      sssa
next数组  0120(其实就是在计算前缀)
计算next数组也是有两个下标计算,建议对照下面代码看 (i为遍历字符串的变量,j为最长前缀的下标)
首先 next[0] 肯定是等于0的,第一个就不匹配,那肯定回溯还是0,
那么 next[1] 由于 str[i] == str[j] 即 str[0] == str[1],s==s,前缀相同,j自然++
next[1]=j,即 next[1]=1
由于本题是 sssa
所以会出现子串      sssa
next数组  012?(题外话,我们知道a是在前面没有最长前缀的,最后结果肯定为0)
匹配到最后一位时,我们发现跟前面不相等,j就看看前面有没有相等的,j=2,但是 str[2] 也不等于 a
然后while循环一直往前找最长前缀(从2到1到0),最终没找到,为0但是,比如子串      aaaab....aaaaa
next数组  01230....0123?(此时j为3,i为n)?处 a和b不匹配,j=next[j-1],即 j=next[3-1],即 j=2,而str[2]==str[n],j++,退出
next[n]=3,这里j没有从0开始,快了一点,其实从0开始也能算出3这个结果最终结果为
子串      aaaab....aaaaa
next数组  01230....01233

上代码

class Solution {
public:int strStr(string haystack, string needle) {// 计算nextvector next(needle.length(), 0);getNext(needle, next);// 匹配过程int j=0;int i=0;for(;i &next) {// j 从 0 开始, i 从 1 开始,已知第一个 next[0] 一定是等于 0 的,因为前面没有字符了for(int j=0,i=1;i 0 && str[i] != str[j]) {j=next[j-1];}// 当前如果匹配,j 往前走if(str[i]==str[j]) {j++;}// j 走多远,前缀最长就是多远next[i] = j;}}
};

相关内容

热门资讯

科普实测“琼戏互娱其实有辅助器... 您好:琼戏互娱这款游戏可以开挂,确实是有挂的,需要了解加客服微信【6355786】很多玩家在琼戏互娱...
删除的文件夹怎么恢复   删除的文件夹怎么恢复?在电脑里有很多文件,为了区分开文件,通常我们都...
最新一款.皮皮衡阳字牌究竟有挂... 最新一款.皮皮衡阳字牌究竟有挂吗.(必胜开挂神器)您好:皮皮衡阳字牌这款游戏可以开挂,确实是有挂的,...
实测分享“皇家大厅透视挂辅助器... 您好:皇家大厅这款游戏可以开挂,确实是有挂的,需要软件加微信【4194432】,很多玩家在皇家大厅这...
今日重大通报“微乐福建麻将究竟... 您好:微乐福建麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【69174242】很多玩家在微...