一眼看懂KMP匹配算法
KMP算法——快速从字符串M(母串)中找出与字符串Z(子串)匹配的子串
例1:
0 1 2 3 4 5
M:a b c a b d
Z: a b d
BF算法(最一般的算法,也叫“蛮力算法”):
将Z[0]-M[0](用“-”表示比较),如果=,则Z[1]-M[1],...直到Z[i]!=M[i],回溯
然后Z[0]-M[1],同上方法~最常见的做法,很容易理解,可是效率比较低。
KMP算法:比较过的字符段也是有信息可以利用的。
如例1,Z匹配M到 Z[2]=d != M[2]=c, 说明什么?说明前面Z[0]=M[0],Z[1]=M[1],一一对应相等。
然后需要回溯让Z[0]去和M[1]比较吗?其实没有必要
为什么? 看Z =ab d d前每个字符各不相同,既然 M=ab cxxxxxx(因为Z与M比较到d,对应的M前面的和Z一一对应相等,可以推测到M失配字符前面的字符),
BF算法是发现不匹配后让Z[0]=a回去和M[i](i=1,2,3...依次递增)比较,只有M[i]=Z[0],才有资格比较M[i+1]和Z[1],继续下一位比较下去,否则判断不等后直接就换下一位了,毫无意义。
但是我们研究了Z后发现 : Z中d前面的字符(ab)串除了Z[0](a)外没有和Z[0]相同的了,那么由于M失配字符之前的字符都是和Z对应相同的,所以推测M失配之前的字符肯定没有与Z[0]相等的,所以他们都没有必要和M[0]去比较 直接可以拿Z[0]从失配点向后比较就可以了。
好吧,我们发现Z上面还是有点信息的(重点理解红字的意思),但还是有点模糊
例2: 0 1 2 3 4 5
M:a b c a b d e a f a f
Z: a b c a b e
看例2.明显Z[5]与M[5]失配。只需要看Z就能推测出M[0]~M[4]是什么。而我们失配之后,下一次匹配比较的前提就是M[i]=Z[0](i=1,2,3....),所以看Z匹配部分
a b c a b ,推测出M对应的M[3]M[4]=ab,下次可以从M[3]开始匹配,有成功可能性。但是如果换成 如下
0 1 2 3 4 5
M:a b c a d d e a f a f
Z: a b c a d e
Z=a b c a d 虽然Z[3]=Z[0],但明显Z[4]!=Z[1],依然无法匹配,所以我们发现只有Z失配字符前呈现abxxab类型,才可从M对应ab处开始下一次监测匹配,否则M失配前的字符均无法匹配Z(如例1所示),所以也无需进行判断。
所以下一步我们只要知道Z匹配比较到第n位,那么我们通过分析Z的前n-1的字符串,分析它们的对称性,就可以判断出对应M下次开始比较的位置。
数据结构语言只是工具,关键是解决问题的思想。
这就是基本思想,具体代码网上随处可见,就不继续写了,表达可能还是不太清楚,多看两遍理解了思想,就豁然开朗了。
后面补充一种其他算法思想:
RK算法:
一个字符一个字符的比较会不会有点慢呢?
如果把n个字符的Z当成一个数z,把M的n个连续字符子串也当成一个数m。
那么如果z!=m,则M对应的该子串肯定和Z不同;反之,z=m就有很大可能相同了,只需要在一个较小的范围内逐个字符比较就好,反正又不多。
M:a b c a b d e a f a f m=abcabd
Z: a b c a b e z=abcabe
不等?m=bcabde(向后移动一位),继续比较,直到m=z,然后比较Z和M子串。其实挺快的这个方法~具体代码网上找
一眼看懂KMP匹配算法的更多相关文章
- 搞定KMP匹配算法
KMP算法介绍及实现——轻松搞定KMP匹配算法 本文介绍了字符串匹配算法中的BF算法和KMP算法.本文中KMP算法介绍部分是关于KMP算法相关文章中最简洁的一篇文章之一.下一篇将继续介绍Horspoo ...
- 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
课本源码部分 第4章 串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版 源码使用说明 链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...
- 数据结构——串的朴素模式和KMP匹配算法
一.朴素模式 假设我们要从主串S="goodgoogle"中找到子串T="google"的位置,步骤如下: i表示主串的当前位置下标,j表示子串的当前位置下标, ...
- c语言KMP匹配算法与字符串替换算法
一.字符串匹配算法 (1)传统匹配算法BF int Index_BF(char* S, char* T){ int i=1,j=1; while(i<=strlen(S) && ...
- KMP匹配算法 - Number Sequence
Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M ...
- KMP匹配算法
先来说一下回溯法匹配字符串: 对于主字符串有一个target_index,以target_index(不动)为起点,匹配字符串pattern的长度+target_index为终点,逐个进行比较,当发现 ...
- 一眼看懂深浅拷贝(clone)-C#
这是使用的是序列化的方式实现深拷贝 [Serializable] class Person:ICloneable { /// <summary> /// 字符串在clone 中类似于值类型 ...
- linux tar 命令 --致力于“一眼看懂,随手就用”的随笔
基本玩法: 压缩: tar -czf txt.tar.gz *.txt // 将当前目录下的所有txt文件,创建一个tar包,并用gzip算法,压缩成txt.tar.gz 文件 解压: tar -xz ...
- 一眼看懂promise async的区别
// promise方法 let p1 = new Promise((resolve,reject) => { setTimeout(() => { resolve('我是p1') },4 ...
随机推荐
- C#自定义大小与改变大下的方法
在用VS的窗体设计器时,我们可以发现控件都是可以拖动的,并且还可以调整大小.怎么在自己的程序中可以使用上述功能呢? 下面的方法值得借鉴! using System; using System.Wind ...
- 使用Spring AsyncRestTemplate对象进行异步请求调用
直接上代码: package com.mlxs.common.server.asyncrest; import org.apache.log4j.Logger; import org.springfr ...
- [bzoj1935][shoi2007]Tree 园丁的烦恼(树状数组+离线)
1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec Memory Limit: 357 MBSubmit: 980 Solved: 450[Submit][ ...
- md语法之行内代码和代码片续集
md语法之行内代码和代码片 一行之内嵌入一小段代码, 简称行内代码. 其方法为: 用撇号把代码围起来. 比如: import numpy as ny就可以了. 代码片的方法: 三个连续的撇号+pyth ...
- css动画属性性能
性能主要表现:流量.功耗与流畅度 在现有的前端动画体系中,通常有两种模式:JS动画与CSS3动画. JS动画是通过JS动态改写样式实现动画能力的一种方案,在PC端兼容低端浏览器中不失为一种推荐方案. ...
- RansomNote
Given an arbitrary ransom note string and another string containing letters from all th ...
- spring aop 利用JoinPoint获取参数的值和方法名称
AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点 ...
- SQLserver2008数据库备份和还原问题(还原是必须有完整备份)
首先,我要说明的是你必须拥有完整的数据库备份,下面的还原教程,才算有用,如果其它问题,请搜索别的大牛的解决办法,本方法只适合菜鸟. 这个连接是站长大人的异常恢复方法,有问题可以自己学习http://w ...
- VNC SERVER配置
vnc的配置网上有很多 普通用户的配置没有怎么写 根据下面这个说法 https://www.digitalocean.com/community/tutorials/how-to-install-an ...
- Android N preview 试用
一.下载更新包 下载地址:https://developer.android.com/intl/zh-cn/preview/download.html 注意下载适合你手机的安装包哦 二.把你手机的oe ...