字符串匹配算法系列一: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 ...
随机推荐
- 最好用的远程连接工具TeamviWer13安装教程(Win10环境)
1.Teamviwer官网:https://www.teamviewer.com/zhCN/ 2.下载链接:https://dl.tvcdn.de/download/TeamViewer_Setup. ...
- [python][django学习篇][9]设计正在博客视图(3)
需求: 真正的首页视图函数,当用户访问我们的博客首页时,他将看到我们发表的博客文章列表,就像 演示项目 里展示的这样.t https://docs.djangoproject.com/en/1.10/ ...
- Spring MVC请求参数绑定
所谓请求参数绑定,就是在控制器方法中,将请求参数绑定到方法参数上 @RequestParam 绑定单个请求参数到方法参数上 @RequestParam("id") Integer ...
- 用jquery实现平滑的页面滚动效果
通过几句jquery代码实现页面平滑滚动到某一锚点的效果.实现代码来源于https://css-tricks.com/snippets/jquery/smooth-scrolling 实现的jquer ...
- Codeforces 1158C Permutation recovery
https://codeforces.com/contest/1158/problem/C 题目 已知 $p_1, p_2, \dots, p_n$ 是 $1$ 到 $n$ 的一个排列. 给出关于这个 ...
- POJ 1753 Flip Game(高斯消元+状压枚举)
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 45691 Accepted: 19590 Descr ...
- POJ 1815 Friendship(字典序最小的最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 10744 Accepted: 2984 Descr ...
- BZOJ3524 [Poi2014]Couriers 【主席树】
题目 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. 输入格式 第一 ...
- 雪人(snowman)
test1025 五子棋(fir) 依照题意模拟即可,先判是否合法,然后在判是否胜利 迷宫(maze) 折半搜素裸题 雪人(snowman) 二分+hash a1-b1=a2-b2=a3-b3 等价于 ...
- 洛谷 P1174 打砖块
题目描述 小红很喜欢玩一个叫打砖块的游戏,这个游戏的规则如下: 在刚开始的时候,有n行*m列的砖块,小红有k发子弹.小红每次可以用一发子弹,打碎某一列当前处于这一列最下面的那块砖,并且得到相应的得分. ...