KMP算法详解:原理、实现及代码示例
创作时间:
作者:
@小白创作中心
KMP算法详解:原理、实现及代码示例
引用
1
来源
1.
https://www.cnblogs.com/perngfey-note/p/18095672
KMP算法是一种高效的字符串匹配算法,通过预处理模式串,避免了在匹配过程中不必要的回溯,从而提高了匹配效率。本文将详细介绍KMP算法的核心思想、前缀表的计算方法以及具体的实现代码。
应用于字符串匹配,主要思想就是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,利用这些信息避免从头再做匹配。
如何利用已经匹配的文本内容?前缀表
前缀表:用来回退,记录模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
- 前缀:不包含最后一个字符的所有以第一个字符开始的连续子串
- 后缀:不包含第一个字符的所有以最后一个字符结尾的连续子串
示例
文本串:a a b a aba a f a
模式串:a a b a af
匹配的过程中文本串b和模式串f 不匹配,而模式串f之前的部分字符串(aabaa)的最长相等的前缀和后缀字符串是字符串aa,因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串后面,我们可以找到与其相同的前缀的后面重新匹配即可,这样避免匹配失败就从头匹配的复杂度过高问题,利用了已经匹配的信息。
如何计算前缀表
example: a a b a a f
- 对于前1个字符的子串a, 最长相同前后缀长度为0
- 对于前2个字符的子串a a, 最长相同前后缀长度为1
- 对于前3个字符的子串a a b, 最长相同前后缀长度为0
- 对于前4个字符的子串a a b a, 最长相同前后缀长度为1
- 对于前5个字符的子串a a b a a , 最长相同前后缀长度为2
- 对于前6个字符的子串a a b a a f, 最长相同前后缀长度为0
前缀表和模式串联系在一起,具体如图:
前缀表与next数组:next数组可以是前缀表,也可以是前缀表统一减一
时间复杂度分析:设文本串长度为n, 模式串长度为m,匹配的过程中不断根据前缀表调整匹配的位置,可以看出匹配的过程是O(n)(因为前缀表使得文本串中不需要回退位置,只需要每次从匹配错误的位置重新匹配,因此是O(n),位置调整是基于模式串调整的),单独生成next数组需要时间复杂度O(m),整个KMP算法的时间复杂度是O(n+m)的。
构造next数组:计算模式串的前缀表
统一减一的前缀表:与索引相匹配
void getNext(int* next, const string& s){
int j = -1;
next[0] = j;
for(int i = 1;i < s.size();i++){
while(j>=0 && s[i]!=s[j+1]){
j = next[j];
}
if(s[i]==s[j+1]){
j++;
}
next[i]=j;
}
};
与前缀长度相匹配:
void getNext(int* next, const string& s){
int j = 0;
next[0] = j;
for(int i = 1;i<s.size();i++){
while( j > 0 && s[i] != s[j]){
j = next[j-1];
}
if(s[i] == s[j]){
j++;
}
next[i] = j;
}
};
leetcode28
class Solution{
public:
void getNext(int* next, const string& s){
int j = -1;
next[0] = j;
for(int i = 1; i < s.size();i++){
while(j >= 0 && s[i] != s[j+1]){
j = next[j];
}
if(s[i] == s[j+1]){
j ++;
}
next[i] = j;
}
}
int strStr(string haystack, string needle){
if(needle.size()>haystack.size()|| needle.size()==0){
return -1;
}
int next[needle.size()];
getNext(next, needle);
int j = -1;
for(int i = 0;i<haystack.size();i++){
while(j>=0 && needle[j+1]!=haystack[i]){
j = next[j];
}
if(haystack[i] == next[j+1]){
j++;
}
if(j == needle.size()-1){
return(i-needle.size()+1);
}
}
return -1;
}
};
热门推荐
永福罗汉果甜苷ⅡA:科学降糖新星
牟氏庄园:胶东大地主的豪宅探秘
探访牟氏庄园:揭秘晚清名人的奢华生活
练了三年《易筋经》,令狐冲的内力为何还是很弱?
农业项目管理是干什么的
书写自己人生的故事:当你开始了写日记的习惯,你会收获5大好处
写日记也能减压?科学证明有效!
饮食日记:记录个人饮食,对健康的益处与方法
柯洁退赛风波:LG杯韩国新规则引争议
柯洁退赛背后:职业棋手如何应对心理压力?
儿童暴力频发,专家教你如何干预
儿童暴力行为背后的深层原因与应对之道
孩子身高比同龄人都矮,怎么办?
现代科技赋能汉阳陵文物保护工作——着衣式陶俑的科技检测研究
千味央厨:以产业帮扶新模式助力乡村振兴
丙酸氟替卡松乳膏正确使用的说明
脱腋毛后如何正确护理肌肤?专业美容师详解术后修复指南
夏季腋下护理秘籍:告别尴尬异味!
当代德国人眼中的希特勒:复杂多面的审视
卫龙酸辣魔芋爽:舌尖上的安全如何保障?
高草酸食物盘点及低草酸蔬菜推荐
揭开“草酸艾滋”的神秘面纱:科学认知与健康警示
《熊出没》春节档再创佳绩:从“追赶者”到“领跑者”的动画传奇
《熊出没·原始时代》:一部让家长也感动的动画电影
新春红色翻领拉链毛衣的多样时尚穿搭指南
腊月25日:新年的序曲,丰富多彩的民间习俗
首个“非遗”春节 全国各地年味十足 尽享视觉盛宴
自制卫龙酸辣魔芋爽,你敢挑战吗?
分道扬镳!小沈阳与本山传媒解约,真实原因离谱,走小沈龙老路
高速堵车应急尿袋成救星?这些神器让你从容应对尴尬时刻