KMP算法的学习经验

(欢迎指正错误, 欢迎喷)

  1. 什么是kmp(完)
  2. kmp的额外知识(完)
  3. 暴力匹配的缺点,和代码实现(完)
  4. next[]数组的预先知识,了解前后缀,相同前后缀。(完)
  5. kmp的关键next[]数组, next的实现。(完)
  6. next数组中k = next[k]的理解。
  7. kmp的优化(待续。。)

一.什么是kmp

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)
————来自百度百科
简单的说 :
1.kmp是一种字符串匹配算法。
2.它的优点就是能通过 next[]数组(一个记忆数组),减少匹配的次数, 从而节省时间。
3.关键是next[] 这个记忆数组。

二.kmp的额外知识

由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)
并且kmp被很多人叫做,看(k)毛(m)片(p)算法。

三.普通暴力匹配


//ptr[] 匹配串, str[] 主串

1.暴力匹配
我们的普通暴力匹配是 匹配串ptr 的字符一个一个和 主串匹配。
如果一个字符匹配成功:ptr的下一个字符继续匹配,
如果失败 :str[]回溯到开始匹配的位置(i = i - j, <-下面有讲解),然后再以 下一个位置为开始, 再次重新进行字符串匹配

暴力匹配代码:

int plen = strlen(ptr);//匹配串的长度
int slen = strlen(str);//主串的长度
int i, j = 0; //i 和j 分别代表 当前 str 和ptr 所匹配的字符下标
int flag = 0;//如果为 1 表示 主串中存在 匹配串。
for(i = 0;i < slen;i++)
{if(str[i] == ptr[j])//如果匹配成果 继续下一个匹配{j++;}else//如果 不相等 {i = i- j;//主串回溯, i回到匹配前的位置j = 0;//匹配串 要从头开始}if(j == plen)// 主串中存在客串 匹配串成功{flag = 1;break;//结束}
}

以上是暴力匹配 的代码, 这也能解决字符串匹配的问题(这种方法没有一点错误), 然而你用这种方法去解题,很多题只能送你个:

acmer的你,看到这就是很尴尬了。
为什么呢?
因为你暴力匹配太盲目了, 而kmp确实聪明的 kmp的j知道往哪跳。

四. 相同前后缀的讲解:

1.什么是前后缀。
如:ABCD这个字符串
A
AB
ABC
就是他的前缀。

BCD
_CD
__ D
就是它的后缀。
·下划线只是营造效果, 没有意义。

2.相同前后缀:
如:ABCAB这个字符串
AB(前缀) AB(后缀) 就是相似前后缀(而且AB是最长的相似前后缀)。

五.kmp的next数组

kmp 通过next数组, 保留了ptr(匹配串)以每个字符结尾的子串的 最长相同前后缀的长度。通过next 主串就不用回溯, 只需ptr(匹配串)来回的跳(有想法的跳 o(* ̄︶ ̄ *)o)就行。
{
如:1. 主串ABCABCABD 客串ABCABD
2.当匹配到:
ABCABCABD
ABCABD 与其失配。
但是我们已经匹配了ABCABCABD 这个AB 我们已经知道他匹配,
所以根据ptr的 前后缀相似的性质(ABCABD), 直接跳到相似前缀的哪里 接着往后匹配。
所以就要知道next数组怎么获得。

}

那么接下来就看个有图的栗子(例子):
主串:ABABAC
匹配串: ABAC

/***next数组的获取*/
int Get_next()
{int plen = strlen(ptr);next[0] = -1;int k = -1;//表示上一次匹配的最长前后缀长度for(i = 0; i < plen; i++){if(k == -1 || ptr[i] == ptr[k])// ptr[i]是后缀的对后一个字符, ptr[k]是前缀的最后一个字符。 k = -1是以第一个字符结尾的子字符串没有前后缀,因此就要有个操作, 解决 第一个字符串就匹配失败的情况。{k++;//如果本次匹配成功 , 长度加一next[i+1] = k;//数组储存}else//不成功{i--;//主串不动k  = next[k];//长度缩减再次匹配, 对于k为什么等于next[k] ,后续会有讲解。}}
}
/***kmp 匹配过程****/
int kmp(char str[], char ptr[])
{int flag = 0; // flag = 1 表示 主串中含有 匹配串int slen = strlen(str);int plen = strlen(ptr);int i, j = 0;for(i = 0;i < slen;i++){if(j == -1||str[i] == ptr[j])//j == -1是:当第一个字符串就不匹配时, 整个匹配串要整体往右移一个。{j++;}else {i--;j = next[j];//匹配失败 j 跳到一上一个字母结尾的前缀后面+1处,}if(j == plen){flag = 1;break;}}return flag;
}

六. k = next[k]的理解:

其他大佬对k = next的理解入口->
本人的讲解:
当匹配失败时 主串 i会停留不动,
k 会都等于 next[k]。

一下图片是 AAACAAAA和它next[]数组情况正确

接下来是过程

深入了解kmp 请看大牛的讲解->

转载于:https://www.cnblogs.com/TJack/p/10526956.html

KMP算法的学习经验相关推荐

  1. KMP算法代学习之(二)代码深入学习

    前段时间学习了KMP算法,感觉略懂略懂!但算法这个东西理解一定要深入,不是略懂略懂就能敷衍过去的!真真做题的时候,才发现仅仅套模板是根本没用的,必须自己写得来代码,这样的话才能从细节,从根本上了解KM ...

  2. 小白一路走来,连续刷题三年,谈谈我的算法学习经验

    数据结构与算法应该算是一个比较难的模块,从小白一路走过来,从大一连续刷过好几年题,看过挺多书,踩过挺多坑,也涨了一些经验,姑且在这里分析一波对数据结构与算法 的学习经验,请耐心看完,相信对你会有所帮助 ...

  3. 字符串匹配——KMP算法

    字符串匹配--KMP算法 ​ 字符串匹配是计算机编程中最常使用到的基础算法之一.字符串匹配相关的算法很多,Knuth-Morris-Pratt(KMP)算法是最常用的之一.最近在学习KMP算法,学习了 ...

  4. 【原创】KMP算法详解

    前言 KMP算法是学习数据结构 中的一大难点,不是说它有多难,而是它这个东西真的很难理解(反正我是这么感觉的,这两天我一直在研究KMP算法,总算感觉比较理解了这套算法, 在这里我将自己的思路分享给大家 ...

  5. 【gif图文】KMP算法(从暴力匹配到快速匹配)

    从暴力匹配到快速匹配(KMP算法) 学习kmp算法前,首先要先了解什么是kmp算法,kmp算法具体优点是什么,kmp的主要应用方向在哪. 然后才是,代码实现 带着以上问题,我们来一步一步学习kmp算法 ...

  6. 开玩笑呢?学习KMP算法能改变自我认知? | 原力计划

    作者 | 落阳学编程 责编 | 王晓曼 出品 | CSDN 博客 前言 近日被朋友问到了字符串匹配算法,让我想起了大二上学期在一次校级编程竞赛中我碰到同样的问题时,为自己写出了暴力匹配算法而沾沾自喜的 ...

  7. 字符串匹配算法——KMP算法学习

    KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...

  8. 授人以渔:分享我的算法学习经验

    前言 看到知乎上有很多人提问"怎么学习算法"?对于这个问题,我想我是非常有资格回答的,因为我不是计算机科班出身,工作几年后通过自学,不仅转行做了推荐算法,而且我的算法水平无论是在公 ...

  9. 学习KMP算法(详解)

    KMP算法是一个广泛应用于字符串查找与匹配的算法,特点就是计算速度快,例如在m长度的字符串中查找匹配长度为n的字符串,他的时间复杂度可以是m+n 对于字符串的查找与匹配,要是我们没有学习过数据结构或者 ...

最新文章

  1. Oracle集合数据类型的比较
  2. 过滤器过滤特定的url_如何从过滤器中排除URL
  3. 廖雪峰js教程笔记11 操作DOM(包含作业)
  4. Github desktop界面全白怎么办?[已解决]
  5. ACR122U Android端应用开发入道指南
  6. python字典包含指定键_筛选python字典中键包含特定字符串的项
  7. 文件无法删除 你需要计算机管理员 提供的权限才能对此文件进行更改解决办法
  8. 全智通A+常见问题汇总解答—A+库存盘点,点击生成盘点,生成错误的数据
  9. Machine Learning系列--L0、L1、L2范数
  10. Android studio 编译错误:CreateProcess error=206, 文件名或扩展名太长。
  11. AcWing寒假每日一题 2058.笨拙的手指
  12. android 蓝牙连接rtk,基于Android手机的RTK手簿软件设计与实现
  13. 油溶性量子点(齐岳)
  14. jni调用java数组导致VM aborting,安卓程序莫名闪退
  15. XP如何连接带网口的共享打印机
  16. 电磁炉各主要元件名词,符号及功能解析
  17. Legolas工业自动化平台案例 —— 水源地自动化监控系统
  18. 回归综合案例——利用回归模型预测鲍鱼年龄
  19. [附源码]Java计算机毕业设计SSM高校互联网班级管理系统
  20. stm32中u8,u16,u32的理解

热门文章

  1. oracle 慕课课程_“慕课”在Oracle数据库课程中的应用探讨
  2. python顺时针旋转_Python之二维数组N*N顺时针旋转90度
  3. Django连接数据库增删改查操作
  4. naarray查询 swift_Swift 4最全的新特性详细解析(推荐)
  5. js声明变量的三种方式
  6. 记录ishield遇到的问题的解决过程
  7. python描述器深度解析
  8. freemarker迭代list、map等常规操作
  9. YOLOv5训练coco128数据集流程
  10. 完美图解教程 Linux环境VNC服务安装、配置与使用