网上有很多解释KMP算法的文章,A_B_C_ABC的这篇很详细,反复看了好几遍,总算理解了个大概,但是总觉得没那么爽快。其实,一种算法各人有各人的理解方法,找到适合自己理解的才容易记住。下面是我对这个算法的一些理解:

最普通的字符串匹配算法就不记了,简单贴一下代码

int strstr(char *sub, char* str){

int i=0;

char *p=str, *q=sub;

while(*(p+i)!='\0'&&*(q+i)!='\0'){

if(*(q+i)==*(p+i))

i++;

else{

p++;

i=0;

}

}

if(*(q+i)=='\0')

return p-str;

return -1;

}

下面说说我理解的KMP算法,与普通匹配算法不一样的是,KMP算法在子串匹配失效的时候,下一步并不是重新从子串的头部开始匹配,而是根据一下next函数计算出下一步应该从子串的什么部位开始匹配。举个例子更容易说明

红色为失效位置, '^'表示的当前是指针位置,'~'表示此次匹配A串开始的位置。

若是普通的匹配算法,当失效时,C串指针要回溯到头部,A串指针也要回溯到'~'的下一位。也就是下一步应该是从A的第二字符(e.g. 'b')和C的开头(e.g. 'a')开始匹配。如此循环

直到找到A串中的某一个位置可以匹配C串。

然而从上面的匹配过程中,可以发现A和B的蓝色部分是第一步中已经确认匹配过的,上面四步的匹配其实可以看作是蓝色部分的前半段与后半段在进行比较,而且前三步在蓝色部分就已经匹配失效了,所以这些比较是无谓的,因为它与父串A无关的,是属于子串C本身的信息。只有第四步才涉及了与父串A中的字符('c')的比较

KMP算法正是利用这一点,它事先利用子串本身的信息就计算出当某一次匹配失效时,下一次应该继续匹配的位置。也就是当C串在最后一个'b'匹配失效时,它省略了前三步(1,2,3)无谓的匹配,下一步比较将在'd'与'c'之间进行。这样父串A无需回溯,C串用一个next函数决定它将回溯的位置。所以next函数至关重要,也是这个算法的关键。

从上面的分析可以知道next函数是子串C本身的性质决定的

假设子串

next(j)=k(k>=0): 当P的第 j+1个字符

匹配失败时, 在父串指针不回溯的情况下,下一步将与

比较。next(j)的函数计算可以表达为

当next(j)=k (k>=0)时,子串指针回溯到

的位置,父串指针不变;

当next(j)=-1时,子串指针回溯到头,父串指针前进一步;

在设计计算next值的程序的时候,我们没有必要每一步都去计算maximum(k),可以用递归方式来做

举个例子

假设子串为P:"abacabab", 且我们将要求的是'b'的next值, e.g. next[7]

假设next[0~6]均为已知: next[0]=-1, next[1]=-1 , next[2]=0 , next[3]=-1 , next[4]=0 , next[5]=1 ,next[6]=2

"abacabab"

next[6]=2可以说明P[0~2](蓝)与P[4~6](红)是一样的

要求next[7]的值,我们可以找前6位("abacaba")中最长的前半段与后半段相等的子串,然后比较前半段子串的下一位是否和P[7]相等。在这个例子中, P[0~next[6]](e.g. P[0~2])就是这样的子串,接下来我们比较 c 和 b也就是P[next[6]+1]('c')和P[7]('b').

若相等则 next[7] = next[6]+1

若不等, 我们进一步找更短的前半段与后半段相等的子串,因为aba和aba是一样的, 要找'abacaba'中比'abc'短的这样的子串,相当于找'aba' 中的next[2]值是一样的.也就是next[next[6]]的值。然后再比较P[next[next[6]]+1]和P[7]是否等,若不等则继续找更短的这样子串

在上的例子中 P[next[6]+1]=P[3]('c') ,与P[7]('b')不相等, 但是  P[next[next[6]]+1] = P[next[2]+1] = P[1]('b'), 与P[7]('b')相等

最后可以得到next[7] = next[next[6]]+1 = next[2]+1= 1;

计算next值的代码:

void calnext(char* P, int next[]){

next[0] = -1;           //第一个元素的next总是-1, 因为根据(1) , 我们并找不到一个k比j=0小

for(int i=1; i

int k = next[i-1];     //因为采用递归的方法, 为了计算next[i], 先记录下next[i-1] 而且假设next[i-1]已知

while(P[k+1]!=P[i]&&k>=0){ // 递归

k = next[k];

}

if(P[k+1]==P[i])     //如果相等而结束, 则找到一对长度为k的前缀字串和后缀字串

next[i] = k+1;       //增加了一个相同项

else

next[i] = -1;          //其他情况

}

}

匹配的代码:

int find(char*T, char* pat){

int n = strlen(pat);

int *next = new int[n];

calnet(pat, next);

char *p=T, *q=pat;

int i=0;

while(*p!='\0'&&(*(q+i)!='\0')){

if(*p==*(q+i)){

p++;

i++;

}else{

if(i==0)

p++;

else

i = next[i-1]+1;

}

}

if(*(q+i)=='\0')

return p-T-n;

else

return -1;

}

记录一下自己理解的KMP以免以后自己都忘记当时怎么理解的。

字符串匹配KMP算法设计C语言,KMP字符串匹配算法笔记相关推荐

  1. kmp算法的c语言,KMP算法 纯C实现

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 我自己写的KMP算法: int nt[256]; void get_next1(char* T, int next[], int tlen) { int  ...

  2. c语言kmp算法代码,C语言KMP算法的实现

    KMP算法在模式与主串之间存在许多"部分匹配"的情况下,比BF算法快.(注意,接下来的串都是以下标为1作为起始储存位置.) 下面说一下实现代码: 首先是预定义和类型定义: #def ...

  3. 数据结构与算法分析(十六)--- 如何设计更高效的字符串匹配算法?(BF + RK + KMP + BMH)

    文章目录 一.Brute Force 匹配算法 二.Rabin–Karp 匹配算法 三.Knuth–Morris–Pratt 匹配算法 四.Boyer-Moore-Horspool 匹配算法 五.字符 ...

  4. 字符串匹配--Sunday算法 1

    字符串匹配(查找)算法是一类重要的字符串算法(String Algorithm).有两个字符串, 长度为m的haystack(查找串)和长度为n的needle(模式串), 它们构造自同一个有限的字母表 ...

  5. 【GO语言实现字符串匹配算法-KMP算法】

    [GO语言实现字符串匹配算法-KMP算法] KMP算法原理说明: KMP算法是一种改进的字符串匹配算法,是有D.E.Knuth,J.H.Morris和V.R.Pratt提出的,所以被称为KMP算法. ...

  6. 【超详细图解】字符串匹配Boyer-Moore算法:文本编辑器中的查找功能是如何实现的?

    关于字符串匹配算法有很多,之前我有讲过一篇 KMP 匹配算法:图解字符串匹配 KMP 算法,不懂 kmp 的建议看下,写的还不错,这个算法虽然很牛逼,但在实际中用的并不是特别多.至于选择哪一种字符串匹 ...

  7. 字符串匹配——Sunday算法

    字符串匹配--Sunday算法 基本思想及举例 Sunday算法由Daniel M.Sunday在1990年提出,它的思想跟BM算法很相似:1 只不过Sunday算法是从前往后匹配,在匹配失败时关注的 ...

  8. 字符串匹配 - RK算法

    名称来由 RK 算法的全称叫 Rabin-Karp 算法. 它是由两位发明者 Rabin 和 Karp 的名字来命名的算法. 实现思路 BF算法的实现思路是对主串n中的每一个连续子串n1,都与模式串m ...

  9. 字符串匹配——BMH算法

    字符串匹配--BMH算法 给定主串T和模式串P,返回P在T中首次出现的位置,如果P不存在于T中,返回-1. 这样的问题就是字符串匹配问题,这里给出BMH算法的思想. 设主串T的长度为n,模式串P的长度 ...

最新文章

  1. 硬中断与软中断的区别!
  2. Fiddler 发送post 请求失败
  3. 数学图形(2.19) 利萨茹3D曲线
  4. axis WebServices 完美调用天气预报,查询、显示 代码!
  5. 分形之龙形曲线(Dragon Curve)
  6. C#使用Xamarin开发可移植移动应用(4.进阶篇MVVM双向绑定和命令绑定)附源码
  7. 查询列名在哪张表_SQL—多表查询
  8. (50)IO的延迟约束(输入延迟约束)
  9. java中如何播放背景mp3音乐_java播放背景音乐
  10. oracle 表空间达到32g,oracle表空间到32G后扩容
  11. Motorola ME525 刷机教程
  12. 安卓开发旅之百度导航
  13. oppoa9处理器怎么样_oppo a9是什么处理器
  14. TCR-T细胞治疗最新研究进展(2021年2月)
  15. 微信小程序分析送积分功能如何实现_微信积分小程序特色功能——积分营销
  16. 2022年终总结——工作第五年
  17. 在“颜值至上”的互联网时代,我们是否需要美颜SDK?
  18. 013 gtsam/examples/ISAM2Example_SmartFactor.cpp
  19. 医咖会免费STATA教程学习笔记——日志文件
  20. 国际象棋ai下载_国际象棋AI的解剖

热门文章

  1. Android学习之基础知识十一 —运用手机多媒体
  2. JavaScript基础介绍
  3. 在用到select2时,临时抱佛脚学习了一下
  4. SQL Server中TEXT类型操作
  5. 【转载】中国小吃(英文表达)
  6. 文本编码与解码问题解决方案
  7. No module named flask.ext.script 解决方法
  8. angular--解决angular图片加载失败问题
  9. 推荐系统的公平性:用户侧与生产侧
  10. Kaggle竞赛宝典方案汇总