讲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. LeetCode_Edit Distance

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

  2. bzoj4033

    http://www.lydsy.com/JudgeOnline/problem.php?id=4033 树形DP. 我们发现,每条边都是一条桥,若我们知道这条边其中一侧有多少个黑点,我们就可以知道这 ...

  3. C# - List操作- 去掉重复

    ChangeList里面会有重复的数据,这时可以这样去掉重复的item // Remove duplicated info var dup = ChangeList.Where(item => ...

  4. js基础例子

    创建变量 var obj=value; 其中obj是变量名; value表示可能是数字,数组,函数之类的 多变量进行计算 var a1=200,b1='hello',c1=400; var d1=c1 ...

  5. 小米路由器mini如何设置外网访问wan网站的方法

    很多的玩友都在小米路由器mini上面搭建了自己的网站,有些朋友还需要设置对外网进行开放,我自己也在路由器上面实践了使用,下面与大家分享一下如何设置外网访问路由器网站的办法. 工具/原料 小米路由器mi ...

  6. XMPP通讯开发-服务器好友获取以及监听状态变化

    在 XMPP通讯开发-好友获取界面设计   我们设计了放QQ的列表功能,这里我们获取我们服务器上的 数据. 这一部分知识我们可以查看smack_3_3_0/smack_3_3_0/documentat ...

  7. 住javaWeb分页实现(模拟百度首页)

    本文来源于 http://blog.csdn.net/tjpu_lin/article/details/41050475 近期在开发一个项目,项目中有非常多数据展示的模块.所以要用到分页,网上搜了非常 ...

  8. 可用与禁用 E:enabled { sRules }

    <!DOCTYPE html><html lang="zh-cmn-Hans"><head><meta charset="utf ...

  9. Android入门2:从GridView控件使用到自定义Adapter

    在日常手机app的使用中,出现频率最高的便是ListView和GridView.ListView的例子是微信主界面,而GridView的例子则是支付宝的主界面,不明白的小伙伴打开手机便一目了然.然而这 ...

  10. C#读取XML配置文件

    DataSource.xml文件,要放在bin/debug/目录下: <?xml version="1.0" encoding="utf-8" ?> ...