字符串匹配算法系列一:KMP算法原理
本文主要参考了https://mp.weixin.qq.com/s/rbaPmBejID8-rYui35Snrg的表述,加上部分自己的理解
学习任何算法都要了解该算法解决什么问题?我们看看KMP算法主要解决什么问题。我们举一个例子,已知字符串1(ABCABBABAABBA)中查找字符串2(ABCAAB)是否存在,如果存在,字符串2在字符串1中的起始位置是多少?
对于上面这个列子,我们很快就可以回答出来字符串2(ABCAAB)在字符串1中存在,起始位置为5(假设从0开始)
暴力匹配:
不考虑任何效率的问题,当然就是从头到尾比较过去了,比如:
ABCABBABAABBA
ABCAAB→
比较下来,发现从第4个字符开始不同了,那没办法,说明前5个字符不是我们想要的字串,接下来我们就让字符串往前拱一步,继续比较:
ABCABBABAABBA
ABCAAB→
这一轮更惨,第一个就栽了,没关系,继续死磕往前拱:
ABABCBABAABBA
ABCAAB→
这一轮也不咋滴,比较到第3个就歇菜了。只要我们有毅力,这个过程坚持不懈,总能找到(或者找不到)答案。
暴力求解算法的复杂度为:假设长字符串为n,短字符串为m,在最极端的情况下(只有最后m个字符才互相匹配)我们需要走n-m轮,每一轮需要匹配m次,时间复杂度为O(nm)
现在的问题是:有没有更快的方法来找到匹配的字串呢?
KMP算法
KMP算法的核心意思就是:当我们发现一次比较下来字串没有完全匹配的情况下,下一次的比较也许可以不止往前拱一步,也许可以拱N步,关键是,究竟可以拱几步呢?
搞清楚这个问题前,先来搞清楚一个关键信息:“部分匹配值”,官方的解释太啰嗦了,我掰开了揉碎了讲给你听,就是这样:将我们要匹配的字串写出来,写两遍:
ABCAAB→
←ABCAAB
看到了吧,我们让他们一个向左一个向右,相向而行。算一下上一行的右边跟下一行的左边,最多能有几个字符是重合的(注意上一行的首字符不参与这个游戏,否则每个字串都是从头配到尾,就没意思了),这个数值N就是字串ABAAB的所谓部分匹配值,当然,你会发现此时N等于2,因为:
后缀
ABCAAB→
←ABCAAB
前缀
下边的字串再往前走,再也找不到更多的重合的字符了,因此字串"ABAAB"的部分匹配值为2,记为:
ABCAAB
2
来,继续算部分匹配值,接下来缩短一点,将最右边的B去掉,来看ABAA的部分匹配值:
ABCAA→
←ABCAA
显而易见,字串"ABAA"的部分匹配值是1,记为:
ABCAAB
1 2
不断重复上述过程,将每一个字串的“部分匹配值”都算出来,就是所谓的部分匹配表,如下所示。
ABCAAB
00 01 12
好了,花开两朵各表一枝,说回刚刚提到的问题:发现不匹配之后,究竟要向右拱几步呢?答案是:可以往前拱 (N-x) 步。N指的是匹配的字符数,x是部分匹配值,现在我们再把刚开始的步骤再做一遍:
ABCABBABAABBA
ABCAAB→
比较下来发现有3个字符匹配,此时N=4,查表得知ABCA的部分匹配值x=1,因此我们此时可以往前拱 (4-1)步,接下来比较:
ABCABBABAABBA
ABCAAB→
我想大家心中一定有这样一个疑问,为什么可以这样子移动,这样子移动不会漏掉匹配数据吗?
上面一行的红色字体ABCA的最后一个A其实就是ABCA的最长后缀
ABCABBABAABBA
ABCAAB→
下面一行的红色字体的ABCA的第一个字符A其实就是最长前缀
我们移动的目的就是要让最长后缀(A)与最长的前缀(A)重合,也就是让两头的部分匹配的区段重合在一起
为什么可以这样子移动?
因为我们知道ABCA前后缀匹配部分只有A,也就是说ABCABBABAABBA的前缀AB与ABCA的后缀CA是不匹配的。
如果我们把小字符串ABCAAB中的A移动到与ABCABBABAABBA中A前面任何一个位置,比如C位置得到的上下字符一定不匹配,因为它们公共部分只有A
ABCABBABAABBA
ABCAAB
你发现,此时我们就跳过了一些比较循环,让我们整个算法的效率得到极大的提升。其实KMP算法的核心,就是充分利用比较过的未能匹配的字串的信息,而不是一股脑将他们丢弃。
字符串匹配算法系列一:KMP算法原理的更多相关文章
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)
相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...
- 字符串匹配算法——BF、KMP、Sunday
一:Brute force 从源串的第一个字符开始扫描,逐一与模式串的对应字符进行匹配,若该组字符匹配,则检测下一组字符,如遇失配,则退回到源串的第二个字符,重复上述步骤,直到整个模式串在源串中找到匹 ...
- KMP算法原理
前几天在看数据结构与算法,里面提到过kmp算法,一个超级经典的字符串匹配算法.虽然网上有一大堆关于kmp算法的介绍文章,但是我看过之后还是“不明觉厉”.所以打算自己写写,大家一起学习吧. 一.关于KM ...
- 搜索模式| 系列2——KMP算法
给定一个文本txt [0..n-1]和一个模式pat [0..m-1],写一个搜索函数search(char pat [],char txt []),在txt中打印所有出现的pat [] [].可以假 ...
- 讲不明白自杀系列:KMP算法
算法:KMP排序 算法分析 KMP算法是一种快速的模式匹配算法.KMP是三位大师:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,所以取首字母组成KMP. 少部分图片来自孤~影 ...
- 字符串匹配算法之BF(Brute-Force)算法
BF(Brute-Force)算法 蛮力搜索,比较简单的一种字符串匹配算法,在处理简单的数据时候就可以用这种算法,完全匹配,就是速度慢啊. 基本思想 从目标串s 的第一个字符起和模式串t的第一个字符进 ...
- 字符串(2)KMP算法
给你两个字符串a(len[a]=n),b(len[b]=m),问b是否是a的子串,并且统计b在a中的出现次数,如果我们枚举a从什么位置与匹配,并且验证是否匹配,那么时间复杂度O(nm), 而n和m的范 ...
- 字符串匹配算法BF和KMP总结
背景 来看一道leetcode题目: Implement strStr(). Returns the index of the first occurrence of needle in haysta ...
随机推荐
- mini购物车程序
product_list=[("Iphohe",5800),("Mac Pro Book",12900), ("xiaomi 4c",120 ...
- 菜鸟之路——机器学习之线性回归个人理解及Python实现
这一节很简单,都是高中讲过的东西 简单线性回归:y=b0+b1x+ε.b1=(Σ(xi-x–)(yi-y–))/Σ(xi-x–)ˆ2 b0=y--b1x- 其中ε取 为均值为0的正态 ...
- python 打印9*9乘法表
# -*- coding: utf8 -*- # Author:wxq 1. for i in range(1,10): for j in range(1,i+1): print "%d*% ...
- LINUX系统安装MYSQL命令
1.下载安装包 wget http://cdn.mysql.com/archives/mysql-5.6/mysql-5.6.26-linux-glibc2.5-x86_64.tar.gz 2. ...
- http的一些知识
TCP/IP协议分层 应用层 TFP DNS DNS域名解析的过程 在浏览器DNS缓存中搜索 读取系统的hosts文件,查找其中是否有对应的ip 向本地配置的首选DNS服务器发起域名解析请求 HTTP ...
- Python之数据结构:序列
一.序列 1.列表.元组和字符串都是序列 二.序列的两个特点:索引操作符和切片操作符 1.索引操作符:从序列中抓取一个特定项目 下标操作:使用索引获取序列中的单个项目: eg:shoplist[0] ...
- JavaScript中in的用法
JavaScript中的in 操作符是对Object(对象)操作的,并不是针对数组. in 的右边必须是对象变量 例如:var data = {id:1, name:'AAA'};if('name' ...
- HDU 1871 无题
无题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...
- 8个学习.net的博客链接 (以前收藏过更多的,被百度新版搞没了,恨死了)
原文发布时间为:2012-09-18 -- 来源于本人的百度文章 [由搬家工具导入] Simone Chiaretta’s CodeClimber http://www.haacked.com/ ( ...
- 在razor中使用递归,巧用递归
原文发布时间为:2011-04-20 -- 来源于本人的百度文章 [由搬家工具导入] Learning Razor–Writing an Inline Recursive HTML Helper Wr ...