扩展的KMP算法,可以在Ο(n + m)的时间复杂度内计算出模板串与文本串的每一个后缀的最长公共前缀,即LCP(T[i:n],P)。

KMP算法所解决的单模板字符串匹配问题,求得的匹配点是LCP = m的位置,属于该算法的子问题。扩展的KMP算法可以获得更多信息。

定义:文本串长度为n,模板串长度为m

   next[i]:模板串P[i:m]和P的最长公共前缀

   extend[i]:文本串T[i:n]和P的最长公共前缀(待求)

   习惯上使用左闭右开区间,下标从0开始,字符串采用Python的表示法

算法思想:

最大程度利用已匹配的串的信息

算法思路:

假设我们已知了next数组,且当前已知T[p:mx]与P的前缀是匹配的。

设mx表示文本串当前已匹配到的最末位置的下一位置(代比较的位置),p表示与之匹配的模板串与文本串的对齐位置,i表示当前要计算extend值的位置

比较i+next[i-p]与mx的大小关系,分为两种情况

  • if (i + next[i - p] < mx)

如图,我们知道p到mx这一段的文本串与模板串是相等的,根据模板串自身的next数组可以知道文本串的extend值至少是next[i - p],又next数组的定义是“最长”,即确定了下一位不相等。所以extend[i] = next[i - p]

  • else

当i + next[i - p] >= mx时,模板串p-i位置的最长公共前缀超出了已知的文本串的范围。我们最大程度地利用已知信息,i位置的extend长度就应当从mx-i开始扩展,接下来比较T[mx]和P[mx - i](标✦的位置),更新答案和mx、p的值。

匹配算法完毕。接下来我们要考虑模板串的next数组的求法

注意到,   next是模板串与模板串的LCP

      extend是文本串与模板串的LCP

所以——next的生成其实就是自己对自己套用该算法。我们甚至不需要改变代码,只需令T=P,带入函数即可。

实现细节

#1由于模板串在匹配自身时在初始位置完全相同,要避免mx在一开始就跳到末尾,所以要加个特判,当匹配自身时,要跳过第一位开始比较。

#2当i>=mx时要更新mx的值为i,重返暴力操作


模板题:洛谷P5410

AC代码:

void exKMP(const char* P, int* nxt, const char* T, int* ext)  P为模板串,nxt是模板串的next数组,T为文本串,ext储存待求的extend值;当ext==nxt时判断为匹配自身,启动特判

 #include <iostream>
#include <string>
#include <cstring>
#include <iterator>
using namespace std; const int maxn = 1e5 + ;
int nxtP[maxn], Lcp[maxn];
void exKMP(const char* P, int* nxt, const char* T, int* ext) {
int i, mx = , p = , n = strlen(T), m = strlen(P); //mx: Position where doesn't fit.
if (nxt == ext) {
ext[] = n;
p = ; mx = ; i = ;
while (mx < n && mx - i < m && T[mx] == P[mx - i]) mx++;
} else i = ; for (; i < n; ++i)
if (nxt[i - p] + i < mx) ext[i] = nxt[i - p];
else {
if (i >= mx) mx = i; //i >= mx
while (mx < n && mx - i < m && T[mx] == P[mx - i]) mx++;
ext[i] = mx - i;
p = i;
}
return;
}
signed main() {
string T, P;
cin>>T>>P;
exKMP(P.data(), nxtP, P.data(), nxtP);
exKMP(P.data(), nxtP, T.data(), Lcp);
copy(nxtP, nxtP + P.length(), ostream_iterator <int> (cout, " "));
cout<<endl;
copy(Lcp, Lcp + T.length(), ostream_iterator <int> (cout, " "));
return ;
}

扩展的KMP算法图解的更多相关文章

  1. 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案

    之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...

  2. KMP算法图解

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

  3. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

  4. 扩展KMP算法小记

    参考来自<拓展kmp算法总结>:http://blog.csdn.net/dyx404514/article/details/41831947 扩展KMP解决的问题: 定义母串S和子串T, ...

  5. KMP算法模板&&扩展

    很不错的学习链接:https://blog.csdn.net/v_july_v/article/details/7041827 具体思路就看上面的链接就行了,这里只放几个常用的模板 问题描述: 给出字 ...

  6. 神奇的字符串匹配:扩展KMP算法

    引言 一个算是冷门的算法(在竞赛上),不过其算法思想值得深究. 前置知识 kmp的算法思想,具体可以参考 → Click here trie树(字典树). 正文 问题定义:给定两个字符串 S 和 T( ...

  7. 图解算法——KMP算法

    KMP算法 解决的是包,含问题. Str1中是否包含str2,如果包含,则返回子串开始位置.否则返回-1. 示例1: Str1:abcd123def Str2:123d 暴力法: 从str1的第一个字 ...

  8. hdu 4300 kmp算法扩展

    Clairewd’s message Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  9. 初探KMP算法

            数据结构上老师也没讲这个,平常ACM比赛时我也没怎么理解,只是背会了代码--前天在博客园上看见了一篇介绍KMP的,不经意间就勾起了我的回忆,写下来吧,记得更牢. 一.理论准备      ...

随机推荐

  1. Vue项目过程中遇到的小问题

    1.给router-link添加点击事件 <router-link to="" @click.native=""></router-link& ...

  2. VSCode 查看、还原本地代码历史版本

    参考链接:https://blog.csdn.net/luckystar_99/article/details/100583141

  3. springboot集成elk 一: springboot + Elasticsearch

    1.ELK介绍 1> Elasticsearch是实时全文搜索和分析引擎, 提供搜集.分析.存储数据三大功能: 是一套开放REST和JAVA API等结构提供高效搜索功能,可扩展的分布式系统. ...

  4. [转帖]Greenplum :基于 PostgreSQL 的分布式数据库内核揭秘 (上篇)

    Greenplum :基于 PostgreSQL 的分布式数据库内核揭秘 (上篇) https://www.infoq.cn/article/3IJ7L8HVR2MXhqaqI2RA 学长的文章.. ...

  5. hadoop基本文件配置

    [学习笔记] 5)hadoop基本文件配置:hadoop配置文件位于:/etc/hadoop下(etc即:“etcetera”(附加物))core-site.xml:<configuration ...

  6. (十)EL表达式和JSTL标签快速入门

    目录 什么是 el 表达式 示例:使用EL表达式获取pageContext .request.session.application域中的数据: 示例:使用EL表达式获取Bean属性 获取当前WEB应 ...

  7. python学习——while True的用法

    在学习过程中,经常能遇到采用while True的用法.下面以一个例子进行说明: 建立一个用户登录系统,用户输入用户名和密码,如果正确就可以进入系统. 1.我自己最开始的写法: d = {} #数据库 ...

  8. diy操作系统 0:万事开头难

          许久之前就有写一个tiny的操作系统的打算,但时间和精力关系,想法一直没有成为最终的代码.操作系统的构建本身是个系统工程,门槛较高,需要多方面的知识,往往几行代码背后是厚厚的几本书才能说清 ...

  9. (转)从0移植uboot (一) _配置分析

    ref : https://www.cnblogs.com/xiaojiang1025/p/6106431.html 本人建议的uboot学习路线,先分析原有配置,根据现有的配置修改.增加有关的部分, ...

  10. APK反编译教程

    在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用 ...