扩展的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. ipad 没有数据线如何上传文件到局域网windows PC 的解决方案

    是的,ios 的封闭性,真麻烦,不想用数据线,还不想用iTunes ,那你找对了. 方案一: (好像只能上传文件,不能下载,能在线查看媒体.) 我的想法是在Windows建立一个http file s ...

  2. leetcode834 Sum of Distances in Tree

    思路: 树形dp. 实现: class Solution { public: void dfs(int root, int p, vector<vector<int>>& ...

  3. yarn和npm

    Yarn和npm命令对比 npm install === yarn npm install taco --save === yarn add taco npm uninstall taco --sav ...

  4. 使用django进行大文件的上传下载

    下载 基于Django建立的网站,如果提供文件下载功能,最简单的方式莫过于将静态文件交给Nginx等处理,但有些时候,由于网站本身逻辑,需要通过Django提供下载功能,如页面数据导出功能(下载动态生 ...

  5. SpringBoot(三)手写starter pom自动配置

    思想:主要是EnableAutoConfiguration在启动的时候会扫描spring.factories并加载 1在resource下面新建META-INF/spring.factories 2在 ...

  6. 【转帖】Linux 内核系统架构

    Linux 内核系统架构   描述Linux内核的文章已经有上亿字了 但是对于初学者,还是应该多学习多看,毕竟上亿字不能一下子就明白的. 即使看了所有的Linux 内核文章,估计也还不是很明白,这时候 ...

  7. 记一次Spring Cloud压力测试

    前言 公司打算举办一场活动,现场参与活动人数比较多.针对于可能访问比较密集的接口进行压力测试.使用jmeter进行测试,请求并发稍微多些,系统就会挂起. 针对压力测试出现的问题,因为并发超过1秒钟10 ...

  8. XDomainRequest IE8&amp;IE9 cors 跨域通讯的处理方法

       版权声明:避免百度一下通片同一篇文章,未经博主允许不得转载.本博客作为笔记使用,正确性请自行验证. https://blog.csdn.net/u014071104/article/detail ...

  9. 解决springboot乱码和window cmd乱码

    @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registration = ...

  10. [Vue]导航守卫:全局的、单个路由独享的、组件级的

    正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的. 记住参数或查询的改变并不会触发进入/离开的 ...