说起kmp就要从字符串的匹配说起,下面我们谈谈字符串的匹配

给定一个原字符串:bababababababababb,再给定一个模式串:bababb,求模式串是否在源字符串中出现

最简单的方法就是遍历源字符串,再遍历模式串,依次进行对比。当遇到不匹配的字符时源字符串和模式串返回下一个位置重新开始匹配,复杂度为n^2。

普通方法其实有可以优化的地方,假设源为字符串Q[1...n],模式串M[1...m]。

按照普通方法Q和M从i,j处进行匹配,当在k位置发生不匹配时,Q返回i+1位置,M返回开始0处重新匹配。

babab|ababababababb  -- i = 5

babab|b    -- j = 5 此处不匹配

b|ababababababababb -- i = 2

bababb  -- j = 0 此处不匹配

bababababababababb

bababb  此处匹配完成

我们从这里思考一下,上式当开始匹配到i=5,j=5时发生了不匹配,下一步就是i返回到i=1,j=0重新匹配,其实i不用返回到1,试想一下Q[1..5]和M[1...5]是匹配的

那么Q[2...5]和M[1...5]是不匹配的,除非Q[1] = Q[2] Q[2] = Q[3] .... 同理Q[3...5]和M[1...5]匹配Q[1] = Q[2] = Q[3] ...,这么说来其实i也不用回溯了,这样j返回到正确的位置就可以继续匹配,那j这个位置怎么确定呢?

j位置无非就是使得Q[i-j, i] = M[1..j] 成立的位置,然后从这个位置继续往下匹配,中间略过的一定是不匹配的,不信自己可以证明一下。再想想刚才说的假设Q[1..i]和M[1...i]是匹配的即 Q[1...i] = M[1...i] 取局部i-j使得Q[i-j...i] = M[i-j...i] 把 Q[i-j, i] = M[1..j]带入得到 M[i-j...i] = M[1...j] 就是说要找的一个位置j使得开始j个长度的字符串等于结尾j长度的字符串。为了不漏掉匹配字符串的长度尽可能长,我们用k表示可匹配的字符串的长度则上述描述变为如下形式

找到 max(k) s.t. M[i-k...i] = M[1...k] 突然发现简单了,可以问题又来了怎么找到这样的k呢?回答是枚举呗k=1,k=2,k=3...找最长的成立的那个代码如下

 def NEXT(pattern):
Next = [0] * (len(pattern)+1)
Next[0] = -1
pattern_len = len(pattern) for i in range(pattern_len+1):
k = 0
for j in range(i):
if pattern[0:j] == pattern[i-j:i]:
k = j
Next[i] = k return Next

好像又回到了出发点还是n^2的复杂度,不行不能这样堕落啊再想想。用Next表示当前模式串改回溯的位置初始化Next[0] = -1

当M[i-k...i] = M[1...k]已经成立,那么Next[i] = k ,当M[k+1] = M[i+1] 时M[i-k...i+1] = M[1...k+1] 因此M[k+1] = M[i+1] 时Next[i+1] = k + 1

当M[i-k...i] != M[1...k]时,k一定是要缩小到,怎么缩小呢?是不是要缩到某个k1的值 s.t. M[i-k1...i] = M[1...k1],如果还不匹配怎么办,继续缩小啊,是不是发现规律了对k = Next[k]不停向前缩小直到找到某个k2的值s.t. M[i-k2...i] = M[1...k2] 然后 Next[i+1] = k2。以上就是Next的递归求解复杂度只要O(m)啊,直接秒杀n^2

 def NEXT(pattern):
Next = [0] * (len(pattern)+1)
Next[0] = -1
pattern_len = len(pattern) for i in range(pattern_len):
j = i
while j > 0:
if pattern[Next[j]] == pattern[i]:
Next[i+1] = Next[j]+1
break
else:
j = Next[j] return Next

Next的使用我就不讲解了,和普通字符串的回溯一样,只不过每次回溯到值都是Next里面的值,将复杂度降低到了O(m+n),代码全部明天贴

KMP学习之旅的更多相关文章

  1. WCF学习之旅—第三个示例之四(三十)

           上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九)   ...

  2. Hadoop学习之旅二:HDFS

    本文基于Hadoop1.X 概述 分布式文件系统主要用来解决如下几个问题: 读写大文件 加速运算 对于某些体积巨大的文件,比如其大小超过了计算机文件系统所能存放的最大限制或者是其大小甚至超过了计算机整 ...

  3. WCF学习之旅—第三个示例之二(二十八)

    上接WCF学习之旅—第三个示例之一(二十七) 五.在项目BookMgr.Model创建实体类数据 第一步,安装Entity Framework 1)  使用NuGet下载最新版的Entity Fram ...

  4. WCF学习之旅—第三个示例之三(二十九)

    上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) 在上一篇文章中我们创建了实体对象与接口协定,在这一篇文章中我们来学习如何创建WCF的服务端代码.具体步骤见下面. ...

  5. WCF学习之旅—WCF服务部署到IIS7.5(九)

    上接   WCF学习之旅—WCF寄宿前的准备(八) 四.WCF服务部署到IIS7.5 我们把WCF寄宿在IIS之上,在IIS中宿主一个服务的主要优点是在发生客户端请求时宿主进程会被自动启动,并且你可以 ...

  6. WCF学习之旅—WCF服务部署到应用程序(十)

    上接  WCF学习之旅—WCF寄宿前的准备(八) WCF学习之旅—WCF服务部署到IIS7.5(九) 五.控制台应用程序宿主 (1) 在解决方案下新建控制台输出项目 ConsoleHosting.如下 ...

  7. WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...

  8. WCF学习之旅—WCF服务的WAS寄宿(十二)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) 八.WAS宿主 IIS ...

  9. WCF学习之旅—WCF服务的批量寄宿(十三)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) WCF学习之旅—WCF ...

随机推荐

  1. 手机app软件开发有什么需要注意的细节?

    在做手机产品设计的过程中,遇到很多看似很小,且很容易被忽略的问题,正是这些手机应用软件开发小问题,一次次的撩拨用户的耐心,让用户对你的产品心生怨念.刚出道的朋友没有经过实战,对细节注意不多,往往都会遇 ...

  2. EL表达式杂项

    1.<%@ page isELIgnored="false" %> 是否忽略EL表达式,如果值为ture,那么  ${..}这样的会直接原样输出,不会进行EL表达式计算 ...

  3. Parseval's theorem 帕塞瓦尔定理

    Source: wiki: Parseval's theorem As for signal processing, the power within certain frequency band = ...

  4. [LeetCode] Remove K Digits 去掉K位数字

    Given a non-negative integer num represented as a string, remove k digits from the number so that th ...

  5. ElasticSearch+Kibana 索引操作( 附源码)

    一 前言 ElasticiSearch 简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elastics ...

  6. "Installation failed !" in GUI but not in CLI (/usr/bin/winusb: line 78: 18265 Terminated )

    "Installation failed !" in GUI but not in CLI (/usr/bin/winusb: line 78: 18265 Terminated ...

  7. Java控制图片按比例缩放- (注意内存释放)

    package mytiny.com.common; import java.awt.Color;import java.awt.Graphics2D;import java.awt.Image;im ...

  8. SQL Server-5种常见的约束

    引自:http://www.cnblogs.com/dekevin/p/4772235.html SQLServer 中有五种约束, Primary Key 约束. Foreign Key 约束. U ...

  9. django 缓存、中间件、信号、CSRF 详解

    中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项 ...

  10. java面向对象---对象初始化

    在本地变量中,如果定义了一个变量后没有赋值就使用,那么eclipse就会报错:但是在成员变量中,java是会强制给一个没有初始化的变量一个默认的初始值0, 如果是一个boolean类型的变量,那么默认 ...