讲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算法总♂结的更多相关文章

  1. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  2. 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)

    前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...

  3. KMP算法解析(转自图灵社区)

    KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...

  4. (原创)详解KMP算法

    KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么 ...

  5. KMP算法 - 求最小覆盖子串

    KMP与最小覆盖子串 最小覆盖子串:对于某个字符串s,它的最小覆盖子串指的是长度最小的子串p,p满足通过自身的多次连接得到q,最后能够使s成为q的子串. 比如: 对于s="abcab&quo ...

  6. KMP算法详解 --- 彻头彻尾理解KMP算法

    前言 之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k. 但是问题在于如何求出这个最大前后缀长度呢? 我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破, 后来翻看 ...

  7. 字符串匹配(KMP算法)

    KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其对于任何模式和目标序列,都可以在线性时间内完成匹配查找,而不会发生退化,是一个非常优秀的模式匹配算法. 举个例子来说,如果 ...

  8. KMP算法与一个经典概率问题

    考虑一个事件,它有两种概率均等的结果.比如掷硬币,出现正面和反面的机会是相等的.现在我们希望知道,如果我不断抛掷硬币,需要多长时间才能得到一个特定的序列. 序列一:反面.正面.反面序列二:反面.正面. ...

  9. Hihocode 1015 KMP算法

    时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. ...

随机推荐

  1. GO的数组及切片

    感觉在向PYTHON学一些数组方面的功能. package main import "fmt" func main() { ]], , , , , , , , , } ] fmt. ...

  2. Unity欢迎窗口的信息

    1.Video Tutorials提供Unity相关的教程,包括用户手册.组件手册以及脚本手册等内容.2.Unity Basics提供Unity的基础知识,例如操作界面.工作流程.发布设置等内容.3. ...

  3. mysql join 的同时可以筛选数据

    看sql ) ) group by a.id; 这里面用了多个子查询,与join关联. 其中 不仅有关联条件,还对sh_mall_goods表进行了筛选,只选出mall_id为9的数据,进行关联. 这 ...

  4. cf442C Artem and Array

    C. Artem and Array time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  5. 第33讲 UI组件_进度条ProcessBar和消息队列处理器handler

    第33讲UI组件_进度条ProcessBar和消息队列处理器handler 1. 进度条ProcessBar 一个可视化的进度指示器,代表正在执行的耗时任务.可以为用户展示一个进度条,表示正在执行的任 ...

  6. Android项目中gen文件下R文件无法生成的解决的方法

    帮一个网友解决R文件无法生成的问题,搜集了些材料特整理例如以下,刚開始学习的人參考他人代码时极易出现此种问题,一般都是xml文件出错,无法被正确解析. gen文件夹无法更新,或者gen文件夹下的R.J ...

  7. Could not load the Tomcat server configuration at /Servers/Tomcat v7.0 Server at localhost-config.

    [问题] Eclipse[Ubuntu14.04]中启动Tomcat Server[7.0.55]的时候出现错误例如以下: [解决方法] 1.将下边的Servers中的server[Tomcat v7 ...

  8. hdu2767 Proving Equivalences --- 强连通

    给一个图,问至少加入�多少条有向边能够使图变成强连通的. 原图是有环的,缩点建图,在该DAG图上我们能够发现,要使该图变成强连通图必须连成环 而加入�最少的边连成环,就是把图上入度为0和出度为0的点连 ...

  9. 【足迹C++primer】46、动态存储类

    动态存储类 StrVec Class Design StrVec Class Definition class StrVec { public: //构造函数 StrVec():elements(nu ...

  10. C#中Property和Attribute的区别

    C#中Property和Attribute的区别 Attribute 字段Property 属性(get;set;) 属性的正常写: private string name; public strin ...