欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > KMP算法(算法篇)

KMP算法(算法篇)

2024/10/24 13:23:25 来源:https://blog.csdn.net/hellmorning/article/details/140573327  浏览:    关键词:KMP算法(算法篇)

算法之KMP算法

KMP算法

概念

  • KMP算法是用于解决字符串匹配的问题的算法,也就是有一个文本串和一个模式串求解这个模式串是否在文本串中出现或者匹配
  • 相对于暴力求解,KMP算法使用了前缀表来进行匹配,充分利用了之前匹配的字符,减少了重新匹配全部模式串的时间。
  • 时间复杂度为O(m+n),其中n为文本串长度,m为模式串长度。

前缀表

例子:文本串:‘aabaabaaf’ ,模式串:‘aabaaf’

  • 前缀表也就是记录模式串的各子串最长相等前后缀长度(即字符串的前缀和后缀相等并且长度最长)的数组,而在KMP算法中是对模式串求解前缀表

  • 前缀字符串除了尾字符的子字符串都是前缀,模式串的前缀有:a、aa、aab、aaba、aabaa

  • 后缀字符串除了首字符的子字符串都是后缀,模式串的后缀有:f、af、aaf、baaf、abaaf

  • image

  • 根据上述的例子可以列出表格:

    image

  • 这样就对应着:aabaaf 010120,这个就为前缀表,而前缀表在KMP算法中被称为next数组或者prefix数组。next的意思就是指通过这个数组可以知晓下一步指针会跳到哪一步。

求解next数组

注:在遍历模式串的各个子串时,i为当前子串的后缀末尾索引j为当前字串的前缀末尾索引并且为数组索引小于等于i之前的子串的最长相等前后缀长度。子串是连续的字符形成的

  1. 初始化j初始化为0,因为模式串的第一个前缀子串为第一个字符,所以j索引指向0的位置,并且next[0]=0i初始化为1,用一个循环从索引i开始遍历模式串。(因为只有一个字符的子串没有相等前后缀)
  2. 前后缀不相同情况:为了充分利用之前已经匹配的字符,我们将对发生冲突的地方也就是前后缀末尾字符不匹配的时候,我们将对前缀末尾索引进行回溯到索引为next[j-1]的位置
  3. 前后缀相同情况当前后缀末尾字符相等的时候,就可以将j++,不仅将当前子串更新到下一个子串,还更新了当前子串的最长相等前后缀长度也就是next[i]=j

实现代码:

void getnext(int *next,const string& s,int size){//初始化int j=0;next[0]=0;for(int i=1;i<size;i++){//前后缀不相等情况while (j>0&&s[i]!=s[j]){j=next[j-1];    //回溯找到相等位置或者回到0}//前后缀相同情况if(s[i]==s[j]) j++;next[i]=j;}
}

KMP具体操作

  1. 求解next数组
  2. 然后利用求解next数组同等思路求解文本串出现模式串位置的索引,求解next数组是模式串前后缀末尾字符的比较,而文本串模式串匹配过程,是文本串与模式串的字符比较过程。
  3. j也就是文本串在索引大于等于i之前的子串与模式串最长匹配字符长度等于模式串的长度,就说明文本串出现了模式串,然后返回文本串中出现模式串的第一个字符的索引值(i-j+1)

KMP算法总体实现代码:

void getnext(int *next,const string& s,int size){//初始化int j=0;next[0]=0;for(int i=1;i<size;i++){//前后缀不相等情况while (j>0&&s[i]!=s[j]){j=next[j-1];    //回溯找到相等位置或者回到0}//前后缀相同情况if(s[i]==s[j]) j++;next[i]=j;}
}int KMP(const string &text,const string &mode){int len=text.size();if(len==0) return 0;int size=mode.size();int j=0,next[size];getnext(next,mode,size);for(int i=0;i<len;i++){while (j>0&&text[i]!=mode[j]){j=next[j-1];}if(text[i]==mode[j]) j++;if(j==size) return (i-j+1);}return -1;    //未找到模式串
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com