KMP算法总♂结
讲KM♂P算法之前,我们先讲一个故♂事。
有一天,sgg给了老obo一封信和一个单词,并给他一个任务:找出这封信出现了多少个单词,然后在规定时间内告诉他。
碰到这个问题,老obo会怎么做呢?
首先最直观的想法是什么?
就是先一维循环枚举信字符串的开头,再一维循环枚举单词的长度,一个一个判断是不是相同。这样的时间复杂度是O(n*m)的,n是信的长度,m是单词的长度。
当n*m小的时候,可以在规定时间内出解,然而,要是n*m很大呢?
我们想想有没有能优化以上算法的方法
我们假设一个next数组,next[i]代表1~i部分的字符串,最长的前缀等于后缀是多长,注意,1~i字符串的长度不能作为next[i]存储的答案。
这样有什么用呢?考虑这样:
我们考虑对单词做出这个数组:next={0,0,0,1,0,0,1,2,0}(从0位置开始)
来模拟一下我们一开始匹配的过程
设定一个指针j,初始在0
我们令i在信中从1扫描到8
:1位置,a[i]==b[j+1],我们令j++
2位置,a[i]==b[j+1],j++
3位置,a[i]==b[j+1],j++
4位置,a[i]==b[j+1],j++
5位置,a[i]==b[j+1],j++
6位置,a[i]==b[j+1],j++
7位置,a[i]==b[j+1],j++
8位置,a[i]!=b[j+1],那怎么办呢,如果让j直接等于0就相当于功亏一篑,于是我们让j=next[j],这样发现,之前匹配的s没有浪费掉,而且节约了时间。然后j=2,我们验证一下,在b中12位置的"sb"正好等于a中67位置的"sb"!
9位置,a[i]==b[j+1],j++
.........
直到11位置,j==m (m为单词长度),这表明了匹配成功!
那么我们怎么求这个next数组呢?
先给出模板
void kmp(){
next[]=;int j=;
for (int i=;i<=m;i++){
while (j>&&b[j+]!=b[i]) j=next[j];
if (b[j+]==b[i]) j++;
next[i]=j;
}
}
就是这么简♂短,首先,next[1]=0,毋庸置疑,我们之前有声明过,next[i]不能等于1~i的长度。
然后对于后面的i,我们已知了next[i-1]的值,我们先让j=next[i-1],
如果b[j+1]=b[i],说明加上这个字符b[i],就等同于在原来相同的前缀后缀都增加了b[i]这个字符。
如果不相同,那就让j=next[j],这个部分比较难理解,我们画张♂图
假设这个字符串是单词,此时我的i已经到了9,j此时是4,当第10个字符出现的时候,如果它"失配"了,那么j=next[j],
其中我们知道,next[4]=2,我们看一下,长度为2的"sx"也正好是这个字符串的前缀和后缀,这是因为,如果我当前的next值为4,那么说明我前缀后缀都包含了"sxsx"这个字符串,当我再度让j=next[j],也就是j从4变成2的时候,"sx"也刚好是他们的前缀后缀了!
这样,O(m)计算next数组的方法就出来了。
obo:那怎么和信匹配呢?
给个模板:
void match(){
int j=;
for (int i=;i<=n;i++){
while (j>&&b[j+]!=a[i]) j=next[j];
if (b[j+]==a[i]) j++;
if (j==m){
printf("Yes!");
return;
}
}
}
是不是很眼熟?没错,和处理next的程序很像,这是因为,kmp中处理next的过程正是"自我匹配"的过程,因为如果a能和b匹配,那a中也包含了b,所以匹配的过程本质是一样的。
KMP算法总♂结的更多相关文章
- 简单有效的kmp算法
以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...
- 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)
前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...
- KMP算法解析(转自图灵社区)
KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...
- (原创)详解KMP算法
KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么 ...
- KMP算法 - 求最小覆盖子串
KMP与最小覆盖子串 最小覆盖子串:对于某个字符串s,它的最小覆盖子串指的是长度最小的子串p,p满足通过自身的多次连接得到q,最后能够使s成为q的子串. 比如: 对于s="abcab&quo ...
- KMP算法详解 --- 彻头彻尾理解KMP算法
前言 之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k. 但是问题在于如何求出这个最大前后缀长度呢? 我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破, 后来翻看 ...
- 字符串匹配(KMP算法)
KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其对于任何模式和目标序列,都可以在线性时间内完成匹配查找,而不会发生退化,是一个非常优秀的模式匹配算法. 举个例子来说,如果 ...
- KMP算法与一个经典概率问题
考虑一个事件,它有两种概率均等的结果.比如掷硬币,出现正面和反面的机会是相等的.现在我们希望知道,如果我不断抛掷硬币,需要多长时间才能得到一个特定的序列. 序列一:反面.正面.反面序列二:反面.正面. ...
- Hihocode 1015 KMP算法
时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. ...
随机推荐
- python的工作记录B
这次很强了.就差最后一步,判断一下SVN的版本是否是真的库里的. #!/usr/bin/env python # -*- coding: utf-8 -*- import os,sys,command ...
- 短信,微信API(还能发邮件,短信,IM聊天)
1.用于微信公众平台的Js API(WeixinApi) Github地址:https://github.com/zxlie/WeixinApi http://www.baidufe.com/item ...
- android开发论坛
http://www.hiapk.com/ http://bbs.hiapk.com/ http://bbs.gfan.com/ http://bbs.anzhi.com/ http://www.ap ...
- paip.索引优化---sql distict—order by 法
paip.索引优化---sql distict—order by 法 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog ...
- Spring中给Bean注入集合
Spring中如果一个Bean里含有集合元素,需要给Bean里的集合元素注入元素时,可以采用如下方法,一个是构造器注入,一个是setter注入 JavaBean源代码: import java.uti ...
- npm 和 bower的区别
npm和bower在功能上有一定的重合,但不是互斥关系,可以在项目中同时运用.区别在于npm在设计之初就采用了的是嵌套的依赖关系树.一个普通的前端包的依赖树比较长,npm 会将开发环境一起下载下来, ...
- python标准库之字符编码详解
codesc官方地址:https://docs.python.org/2/library/codecs.html 相关帮助:http://www.cnblogs.com/huxi/archive/20 ...
- jQuery----blur()方法
当元素失去焦点时发生 blur 事件. blur() 函数触发 blur 事件,或者如果设置了 function 参数,该函数也可规定当发生 blur 事件时执行的代码. 提示:早前,blur 事件仅 ...
- 关于ionic传值
今天,也是偶然发现有的初学者对ionic的传值还不太清除,这里我说明一下 例如你想在这个页面传递参数a.b过去,传递到"tab.wait"页面 $state.go("ta ...
- C++ Primer 学习笔记_84_模板与泛型编程 --模板特化
模板与泛型编程 --模板特化 引言: 我们并不总是能够写出对全部可能被实例化的类型都最合适的模板.某些情况下,通用模板定义对于某个类型可能是全然错误的,通用模板定义或许不能编译或者做错误的事情;另外一 ...