这是我自己学习算法时有关KMP的学习笔记,代码注释的十分的详细,分享给大家,希望对大家有所帮助 在介绍KMP算法之前,

先来介绍一下朴素模式匹配算法:

朴素模式匹配算法:

假设要从主串S=”goodgoole”中找到T=”google”这个字串的位置,我们需要一下的步骤:

1,主串S的第一位开始,S与T的前三个字母都能成功匹配,但是S的第四个字母是d,而T的第四位是g,所以主串S的第一位匹配失败

2,然后从主串的第二位开始,会发现主串的第二位字母与T的第一位字母不同,所以匹配失败,然后再从主串的第三位开始,

3,经过这样的依次尝试后,之到主串的第五位开始,S与T的6个字母完全匹配成功

该朴素模式匹配算法的代码实现是:

该算法的功能是返回字串T在主串S中第pos个字符之后的位置,若不存在,则函数返回值为0,前提是T非空且1<pos<StrLength(S)

int Index(char* S,char* T,int pos)//index是索引的意思

{

int i=pos-1;//i用于主串S中当前位置的下标,S[0]是主串T的第一个字符

int j=0;//j用于子串T中当前位置下标值,即T[0]是字串T的第一个字符

while(i<strlen(S)&&j<strlen(T))

{

if(S[i]==T[j])//如果主串S当前的字母与子串的字母相等则继续

{

++i;

++j;

}

else

{

i=i-j+1;//eg:如果第一次匹配时,不相等则使i=i-j+2=i+1;即向下走一个字母,以i=0为例,刚开始从主串第一个位置开始,如果S[i]==T[j]一直满足,则i和j同步变化,即i=j;一旦有不相等的字母时,i=i-j+1,实际就是i=1;然后再从主串的第二个字母开始

j=0;//重新匹配时,j又回到T的子串的首位

}

}

if(j==strlen(T))//此时已完成匹配

return i-strlen(T);//返回

else

return 0;

}

KMP模式匹配算法

KMP算法中把T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度;

next数组值得推导:

T="abcdex";(前后缀一个字符相等,k值是2,两个字符相等,k值是3,n个k值相等k值就是就是n+1)

1,当j=1时,next[1]=0;

2,当j=2时,j由1到j-1只有字符"a",next[2]=1;

3,当j=3时,j由1到j-1就只有字符串"ab",显然"a"与"b"不相等,所以next[3]=1;

4,同理得:T串的next[j]为011111;

T="ababaaaba";

1,当j=1时,next[1]=0;

2,当j=2时,next[2]=1;

3,当j=3时,next[3]=1;

4,当j=4时,next[4]=2;//j由1到j-1的串是"aba",前缀字符"a"与后缀字符"a"相等,next[4]=2;

5,当j=5时,next[5]=3;//串是"abab",前缀是"ab",后缀是"ab",有两个相同的字符,所以为3

6,当j=6时,next[6]=4;//串是"ababa",前缀是"aba",后缀是"aba",有三个相同的字符,所以为4

7,当j=7时,next[7]=2;//串是"ababaa",前缀字符是"a"与后缀字符"a"相等,有两个相同的字符,所以为2

8,当j=8时,next[8]=2;//串是"ababaaa",前缀字符是"a"与后缀字符"a"相等,有两个相同的字符,所以为2

9,当j=9时,next[9]=3;//串是"ababaaab",前缀字符是"ab",后缀字符也为"ab",有两个相同的字符,所以为3

10,当j=10时,next[10]=4;//串是"ababaaaba",前缀字符是"aba",后缀字符也为"aba",有三个相同的字符,所以为4

KMP模式匹配算法实现

1,通过计算返回子串T的next数组

void get_next(char* T,int *next)

{

  int i,j;

    i=1;

 j=0;

   next[1]=0;

   while(i<=strlen(T))

  {

  if(j==0||T[i-1]==T[j-1])

{

++i;

++j;

next[i]=j;

}//以T="abcdex"为例:该循环的执行顺序:第一步,j=0,执行,(i=2,j=1,next[2]=1)第二步,不符合循环条件,j=next[1]=0,j又变为0为了再次进入循环,(i=3,j=1,next[3]=1)依次往下循环

else

j=next[j];

}

}

//这段代码的目的就是为了计算出当前要匹配的串T的next数组

int Index_KMP(char* S,char* T,int pos)

{

int i=pos;

int j=1;

int next[255];

get_next(T,next);

while(i<=strlen(S)&&j<=strlen(T))

{

if(j==0||S[i-1]==T[j-1])

{

++i;

++j;

}

else

j=next[j];//起到回溯的作用

}

if(j>strlen(T))

return (i-strlen(T)-1);

else

return 0;

}

附加一个实例:

#include<iostream>

using namespace std;

void get_next(char* T,int *next)

{

int i,j;

   i=1; j=0;

  next[1]=0;

 while(i<=strlen(T))

{

if(j==0||T[i-1]==T[j-1])

{             

        ++i;

++j;

next[i]=j;

}//以T="abcdex"为例:该循环的执行顺序:第一步,j=0,执行,(i=2,j=1,next[2]=1)第二步,不符合循环条件,j=next[1]=0,j又变为0为了再次进入循环,(i=3,j=1,next[3]=1)依次往下循环

else

j=next[j];

}

}//这段代码的目的就是为了计算出当前要匹配的串T的next数组

int Index_KMP(char* S,char* T,int pos)

{

int i=pos;

int j=1;

int next[255];

get_next(T,next);

while(i<=strlen(S)&&j<=strlen(T))

{

if(j==0||S[i-1]==T[j-1])

{

++i;

++j;

}

else

j=next[j];//起到回溯的作用

}

if(j>strlen(T))

return (i-strlen(T)-1);

else

return 0;

}

int main()

{

  char* T="bc";

   char* S="babaacbababcbababcbcbc";

   int pos=1;

  int next[255];

  get_next(T,next);

  for(int j=1;j<=2;j++)

   cout<<"j="<<j<<":"<<"next"<<"["<<j<<"]"<<next[j]<<endl;

  cout<<"子串T在主串S第"<<pos<<"个字符之后的第"<<Index_KMP(S,T,pos)<<"个位置"<<endl;

   return 0;

}

转载于:https://blog.51cto.com/zzyleoo/1308240

KMP算法的详细解释及实现相关推荐

  1. 关于 IMCRA+OMLSA 语音降噪算法的详细解释

    关于 IMCRA+OMLSA 语音降噪算法的详细解释 概述 OMLSA 算法 IMCRA 算法 概述 IMCRA+OMLSA 算法及其一些变体是目前语音降噪中常用的算法.很多文献在解释这两种算法的时候 ...

  2. 串—KMP算法(详细)

    KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息.时间复杂度O(m+n). (1)分 ...

  3. KMP算法的浅显解释

    举个通俗的例子解释KMP算法中NEXT[J]: 字符串:abcX 子串 : abcd 当比较到d与X的时候,最原始的算法是子串向后移动一位继续比较 字符串:abcX 子串 : abcd 而KMP则利用 ...

  4. KMP算法——很详细的讲解

    前段时间学习KMP算法,感觉有些复杂,不过好歹是弄懂啦,简单地记录一下,方便以后自己回忆. 引入 首先我们来看一个例子,现在有两个字符串A和B,问你在A中是否有B,有几个?为了方便叙述,我们先给定两个 ...

  5. 【KMP算法】详细讲解

    KMP算法 KMP主要应用在字符串匹配问题上 算法思想:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配,大大降低了时间复杂度,这也就是为什么这类问题我们选择 ...

  6. Gauss-Newton算法代码详细解释(转载+自己注释)

    这篇博客是对[1]中不详细的地方进行细节上的阐述, 并且每句代码都加了注释,使得更加容易理解 下面的论述(包括伪代码和算法)特指被最小化的目标函数是MSE的时候 需要注意,如果不是MSE为目标函数,那 ...

  7. 反向传播算法的详细解释(下)

    上一篇文章算是用"链式法则"给我们开了个头,下一篇文章则是将反向传播算法应用到神经网络. 原文出处:知乎 https://zhuanlan.zhihu.com/p/25081671 ...

  8. 反向传播算法的详细解释(上)

    最近在看NG的视频的时候,学习反向传播算法时遇到了不小的困难.一是因为NG并没有把太多的精力放在讲解反向传播原理上,可能NG自己也觉得这部分如果要细讲,真的会耗费不少时间.二是NG在开课初就很照顾数学 ...

  9. 狄克斯特拉算法(Dijkstra)详细解释

    文章目录 算法用途(目的) 算法思想与本质 图文解释 代码解析 算法用途(目的) 狄克斯特拉算法的用途或者说是目的是计算单源最短路径.单源最短路径的意思是从一个点出发到另外一个点最为的容易.举个例子解 ...

最新文章

  1. 重复数据删除(De-duplication)技术研究
  2. php 最大文件,php读取大文件最好的实现方法
  3. 白夜:一文看懂AI项目流程及边缘设备开发
  4. 谷歌fuchsiaos和华为鸿蒙,华为鸿蒙最大的对手现身!谷歌正式推送Fuchsia OS,或替代安卓...
  5. 【渝粤题库】陕西师范大学164108 网络营销与策划 作业 (高起专)
  6. esp32 micropython spiffs_spiffs 文件系统在esp32中的应用
  7. 串的模式匹配(BF算法)
  8. php判断简写,怎么简写php 中的三元运算符
  9. Python使用pandas对数据进行差分运算
  10. Linux下的信号处理
  11. 蓝桥每日真题之整数分解
  12. OpenStack基金会任命马振强为中国区大使
  13. cpu顶盖怎么看步进_硬核科普丨什么是CPU步进?B0步进和U0步进具体差别有哪些...
  14. 【学习笔记】通过雷达获取某一角度的距离信息
  15. 第1期——WLAN定义和基本架构
  16. python画波浪线_PPT绘制波浪线的四种方法
  17. DCloud的uniapp如何实现微信刷脸支付
  18. android白屏优化方案,优化Android App启动白屏
  19. Spring boot + netty开发即时通讯 IM
  20. 关于宋词频率统计(R语言)

热门文章

  1. 改变人生的32句励志名言
  2. Dan Gillmor总结微软付费平息纠纷历史
  3. mysql join order by_MySQL 14 慢查询优化join、order by、group by
  4. java拍照搜题软件下载_修改版|学生福利!!免费拍照搜题秒出答案,扫一扫作业出答案!...
  5. 远程服务器如何传文件大小,linux服务器远程传文件大小
  6. 2018计算机职称考试题,2018年职称计算机Powerpoint考试试题及答案
  7. php最简单验证码代码,简单好用的PHP验证码类
  8. 简述WSL 2安装和WSL 1转换为WSL 2
  9. 了解下RDF 主要元素
  10. 关于学习Python的一点学习总结(20->assert判断->while和for使用)