KMP学习之旅

说起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...找最长的成立的那个,好像又回到了出发点还是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

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

时间: 2024-12-31 15:57:41

KMP学习之旅的相关文章

基于 Android NDK 的学习之旅----- C调用Java

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html 基于 Android NDK 的学习之旅----- C调用Java许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现. 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法. 1.主要流程 1.  新建一个测试类TestProvider.java a)       

SSIS 学习之旅 序章 和 简介

SSIS 学习之旅目录: 第一章: SSIS 学习之旅 第一个SSIS 示例(一) 第二章: SSIS 学习之旅 第一个SSIS 示例(二) 第三章: SSIS 学习之旅 数据同步 第四章: SSIS 学习之旅 FTP文件传输-FTP任务 第五章: SSIS 学习之旅 FTP文件传输-脚本任务 第六章: SSIS 学习之旅 FTP访问类 SSIS是Microsoft SQL Server Integration Services的简称,是生成高性能数据集成解决方案,是Microsoft BI 解

【转】基于 Android NDK 的学习之旅-----数据传输(引用数据类型)

原文网址:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/20/2147086.html 基于 Android NDK 的学习之旅-----数据传输二(引用数据类型)(附源码) 基于 Android NDK 的学习之旅-----数据传输(引用数据类型) 接着上篇文章继续讲.主要关于引用类型的数据传输,本文将介绍字符串传输和自定义对象的传输. 1.主要流程 1.  String 字符串传输 a)         上层定义一个native的方法

Git命令学习之旅——日志和穿梭版本号

在总结了git命令的基础之后,接下来我们看一下基础的一些进阶内容:删除撤销命令.日志查看命令等 既然有加入文件的功能,那么相相应的肯定有移除文件的功能,命令例如以下:git rm [文件名称] 在输入命令之后,例如以下图所看到的: 提示已经删除了"c.txt"文件.这个时候再用git status查看一下状态,例如以下图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JB

Android热修复学习之旅——HotFix完全解析

在上一篇博客Android热修复学习之旅开篇--热修复概述中,简单介绍了各个热修复框架的原理,本篇博客我将详细分析QQ空间热修复方案. Android dex分包原理介绍 QQ空间热修复方案基于Android dex分包基础之上,简单概述android dex分包的原理就是:就是把多个dex文件塞入到app的classloader之中,但是android dex拆包方案中的类是没有重复的,如果classes.dex和classes1.dex中有重复的类,当classes.dex和classes1

菜鸟的Android学习之旅(一)

最近在拜读郭霖老师的经典<第一行代码>,作为一名菜鸟级的新手来说这本书确实对新手很友好,讲的很详细.如果你也像我一样作为一只小菜鸟想学习Android,还不了解这本书的,还没有想好入手哪一本书作为自己新手启蒙书的同学,个人觉得你就不要徘徊了,加入购物车吧! 因为我才是刚开始学习不久,第二章才学习了很少一部分,所以我没办法说点有营养的东西,我就先记录一下我学习过程中经历的错误吧. 第二章开始,郭老师教我们如何手动创建活动.边看书边敲代码,但是你会发现当你完全按照书上所说敲完所有需要的代码之后代码

iOS学习之旅10 ATS(App Transport Security)对HTTPS协议要求引起的问题

问题描述 编写以下代码获取网络某个资源的MIMEType 1 -(void)getMIMEType 2 { 3 //路径 4 NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/img/bd_logo1.png"]; 5 //请求对象 6 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 7 NSOperationQueue *

c++ hmtlcxx 学习之旅

最近刚网页抓取,抓取下来后需要解析,所以在网上找了一些资料,也问问我的师兄,最终结合网上的开源知识,完成了htmlcxx的使用. vs2013. 首先要去下载htmlcxx: https://github.com/dhoerl/htmlcxx 或者你也可以百度下去下载一个. 接下来,将文件文件解压,我用vs2013将htmlcxx.vcproj打开,点击生成. 生成好就可以,点击调试会有错误,我们也不需要调试. 创建一个win32控制台,直接点击完成. 接下来将debug下的htmlcxx.li

我的AngularJS 学习之旅

基础篇 1.Angular的 起源 2.比较Web 页面实现的几种方式 3.一些基本术语 4.Angular与其他框架的兼容性 5.总结 6.综合实例 很早之前就听朋友说起AngularJs,但由于各种原因,一直没去研究.最近正好有同事也对这个框架比较感兴趣,大家一起讨论,于是终于“名正言顺”地开始研究了. 本文的目的是记录一下自己这两周的学习点滴,算是学习笔记吧,如果对初学的朋友有一点帮助,那也算是一件好事.嘿嘿 1.Angular的 起源 关于Angular 的起源,可以追溯到2009 年的