给定两个字符串A,B,判断T是否为S的子串(变式:寻找子串B在串A中的位置)。

要求一个O(|A|+|B|)的做法。

通常称A为目标串(或主串),B为模式串。

算法过程:

我们假设串A的长度为n,串B的长度为m,每个字符串的开头下标默认为1。

定义两个变量i和j,这两个变量共同表示:A[i-j+1~i]与B[1~j]均匹配,即:A中以第i个字符结尾的、长度为j的字符串,和B从头开始长度为j的字符串完全匹配。

继续往下匹配:如果i+1和j+1不匹配。

现在,就是用到了KMP算法的核心:它对这一情况的处理方式是减少j,就相当于将子串向右平移。

平移的目的是为了让“A[i-j+1~i]与B[1~j]均匹配”这个条件重新满足。

在上图中,j一直减小到了0,因为向右平移的过程中,始终不能让这个条件满足(最右边"?"部分已经越界)

但有时候,将j减少一点点之后,是可以重新满足条件的,例如:

那么我们将j从7减小到4时,有:

这样就可以完全匹配啦!但是后面还有没有匹配的机会我们就不管了,至少我们已经保证A[4~7]和B[1~4]完全匹配上了。

现在考虑一个问题:我们每次把j减小1(一位一位地平移B字符串),这样太慢了,我们在这里预处理一个next[]数组,表示当j匹配不下去的时候,我们可以把j减少到next[j],继续尝试匹配。

预处理过程:让j自己和自己匹配一下,一旦匹配发现B[k-m+1~k] 和 B[1~m] 匹配,则说明在A与B匹配过程中,j等于k匹配不下去时,j可以尝试减小到m。

过程如下:

/**************************************///靓丽的分界线

一些代码:

/*核心内容*/

for (int i = , j = ; i <= n; i++)
{
while (j&&B[j + ] != A[i]) j = next[j];
if (B[j + ] == A[i]) j++;
if (j == m)
{
printf("%d\n", i - j + );//输出找到的"B字串在 A中位置"
//如果要求的是出现次数,这里也有可能是ans++什么的
j = next[j];//让循环进行下去
}
} for (int i = , j = ; i <= m; i++)/*预处理next[]数组*/
{//j在每次循环开始都表示next[i]的值,同时也表示需要比较的下一个位置 while (j&&B[j + ] != B[i]) j = next[j]; if (B[j + ] == B[i]) j++; next[i] = j; }

经典例题:Blue jeans(POJ 3080)

给定m个串,求字典序最小的公共子串。找一个串,使得这个串是所有串的子串,并且字典序最小。

m≤10,每个串的长度≤60.

解题思路:一个串,如果是所有串的子串,那么肯定是第一个串的子串。

枚举所有子串,复杂度为60*60。

验证其它串是否包含这个子串,复杂度为10*60。

每次更新答案即可。

时间复杂度为:O(603×10)

经典例题:Seek the Name,Seek the Fame(POJ 2752)

给定一个字符串S,求所有既是S的前缀又是S的后缀的子串,从小到大输出这些串的长度。

|S|<=500000。

N为字符串S的长度。

解题思路:

回到KMP算法,我们令P[j]表示找最大的数x,使得B中位置是1~x的字符与j-x+1~j的字符完全相同,也就是上面讲的KMP算法中的next[]。

考虑P[|S|]的意义,也就是最大的前缀等于后缀的长度(不包括其本身)。

那P[P[|S|]]就是次大的。

因此所有P[P[…P[|S|]]]就是答案了,一直这样递归下去就可以找到答案。

或者用Hash来做,这样更容易想到也比较方便,但效率没有KMP高。

KMP算法解释的更多相关文章

  1. [Algorithm] 字符串匹配算法——KMP算法

    1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...

  2. 字符串匹配的KMP算法

    ~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...

  3. 深入理解KMP算法

    前言:本人最近在看<大话数据结构>字符串模式匹配算法的内容,但是看得很迷糊,这本书中这块的内容感觉基本是严蔚敏<数据结构>的一个翻版,此书中给出的代码实现确实非常精炼,但是个人 ...

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

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

  5. 字符串匹配的KMP算法详解及C#实现

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

  6. 字符串匹配与KMP算法实现

    >>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个 ...

  7. 数据结构(复习)---------字符串-----KMP算法(转载)

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

  8. 字符串匹配的KMP算法(转)

    转载:http://kb.cnblogs.com/page/176818/ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE&quo ...

  9. 字符串匹配的KMP算法(转)

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

随机推荐

  1. 【安装】ES的安装过程

    1.安装ES 首先我们需要去官网下载安装包  官方下载地址 下载后不需要编译,直接解压 解压后结构是这样的(2.5以上版本会有plugins目录,没有的需要手动创建) 方式一: 创建一个es用户(因为 ...

  2. python之urllib2简单解析HTML页面之篇一

    一.urllib2简单获取html页面 #!/usr/bin/env python # -*- coding:utf-8 -*- import urllib2 response = urllib2.u ...

  3. postgres10.2时区研究

    搭建两个虚拟环境,操作系统均是cents7. 环境A: 使用timedatectl命令查看时区为 Time zone: Asia/Shanghai (CST, +0800). 本地数据库时区(show ...

  4. UVALive-3487 Duopoly(最小割)

    题目大意:有两家公司都想向政府申请某些资源的使用权,并且他们都提供了一些申请列表,列表中含有申请费用和资源种类,同一家公司的申请列表之间不含有重复的资源.政府只可以完整地接受和拒绝谋一份申请列表,问政 ...

  5. UVA-863 Not so Mobile (简单二叉树)

    题目大意:给一个树状天平,判断是否平衡.树状天平是按递归给出的. 题目分析:平衡的条件是子天平都平衡,并且w1*d1==w2*d2,其中w1和w2为子天平的总重量,d1和d2为力矩. 代码如下: # ...

  6. 兼容360模式自动播放视频【需要flvpalyer.swf】

    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://down ...

  7. 本地Run Page时报检测到意外的 URL 参数,它将被忽略。

    经查,是因为我RUN的时候 Target URL -- http://MY-PC:8988/OA_HTML/runregion.jsp 将MY-PC更改为本地IP即可. 设置方法 Tools - Em ...

  8. 5G RRC——为NAS层提供连接管理,消息传递等服务; 对接入网的底层协议实体提供参数配置的功能; 负责UE移动性管理相关的测量、控制等功能

    from:http://www.cnblogs.com/kkdd-2013/p/3868676.html 1 RRC协议功能 为NAS层提供连接管理,消息传递等服务: 对接入网的底层协议实体提供参数配 ...

  9. [转载]字符串匹配的Boyer-Moore算法

    作者: 阮一峰 日期: 2013年5月 3日 上一篇文章,我介绍了KMP算法. 但是,它并不是效率最高的算法,实际采用并不多.各种文本编辑器的"查找"功能(Ctrl+F),大多采用 ...

  10. 006——php字符串中的处理函数(五)

    <?php /** * 一.addslashes() 在预定义字符串前添加反斜杠 * * stripslashes() 把转义字符串前的反斜杠删除 * get_magic_quotes_gpc( ...