对于一个字符串 s 以及子串 t ,扩展KMP可以用来求 t 与 s 的每个子串的最长公共前缀 ext [ i ],当然,如果有某个 ext 值等于 t 串的长度 lent ,那么就说明从其对应的 i 开始的一个长 lent 的子串即为 t 串,因此可以同样线性地求出 s 串中的每个 t 子串的出现位置与出现顺序。

首先感谢 xiaoxin 巨巨,基本是从他的模板上面理解而来的昂。

这里是助于我理解的满满注释版:

 #include<stdio.h>
#include<string.h> const int maxn=1e6+;
inline int max(int a,int b){return a>b?a:b;} int nxt[maxn],ext[maxn];
char s[maxn],t[maxn]; void EKMP(char s[],char t[],int lens,int lent){ //s为字母串,t为子串,并分别传入两串长度,ekmp是求t串与s串每个位置开头的最长公共前缀
int i,j,p,l,k;
nxt[]=lent;j=; //t串自匹配,从t0开始的t的子串(即t串本身)与t串的最长公共前缀定为t串长度,j为已匹配完的位置,j+1即待匹配的位置
while(j+<lent&&t[j]==t[j+])j++; //先匹配t1开始的子串,若依次匹配直到失配
nxt[]=j; //t1开始的子串与t串最长公共前缀长度即为j
k=; //k为除t0外的最远匹配的开始字符,后续每次进行额外匹配就更新它
for(i=;i<lent;i++){ //i表示匹配从ti开始的子串与t串的最长公共前缀
p=nxt[k]+k-; //p即为k所对应的最远失配位置,也是整个t串在自匹配过程中已经匹配到的位置
l=nxt[i-k];
if(i+l<p+)nxt[i]=l; //从ti开始已经确定匹配成功的结束位置与总匹配过的位置p比较,若结束位置小,则说明到i+l出已经失配,ti开始的最长公共前缀即为l,否则对超过p的部分进行匹配,直到失配并更新k
else{
j=max(,p-i+);
while(i+j<lent&&t[i+j]==t[j])j++;
nxt[i]=j;
k=i;
}
} j=; //t与s的每个子串匹配,可以根据之前已经匹配过的s串的部分转化为t串与s中t的子串匹配,首先初始匹配位置赋为0
while(j<lens&&j<lent&&s[j]==t[j])j++; //先匹配s0开始的串和t串的最长公共前缀
ext[]=j;k=; //s0处的最长公共前缀即刚匹配完的j,将最长匹配到的位置对应的s0赋给k,之后进行与t串自匹配基本一样的操作,但是循环的从i=1开始,更新ext数组
for(i=;i<lens;i++){
p=ext[k]+k-;
l=nxt[i-k];
if(l+i<p+)ext[i]=l;
else{
j=max(,p-i+);
while(i+j<lens&&j<lent&&s[i+j]==t[j])j++;
ext[i]=j;
k=i;
}
}
}

这里是为了敲和复制用的并没有注释版:

 #include<stdio.h>
#include<string.h> const int maxn=1e6+;
inline int max(int a,int b){return a>b?a:b;} int nxt[maxn],ext[maxn];
char s[maxn],t[maxn]; void EKMP(char s[],char t[],int lens,int lent){
int i,j,p,l,k;
nxt[]=lent;j=;
while(j+<lent&&t[j]==t[j+])j++;
nxt[]=j;
k=;
for(i=;i<lent;i++){
p=nxt[k]+k-;
l=nxt[i-k];
if(i+l<p+)nxt[i]=l;
else{
j=max(,p-i+);
while(i+j<lent&&t[i+j]==t[j])j++;
nxt[i]=j;
k=i;
}
} j=;
while(j<lens&&j<lent&&s[j]==t[j])j++;
ext[]=j;k=;
for(i=;i<lens;i++){
p=ext[k]+k-;
l=nxt[i-k];
if(l+i<p+)ext[i]=l;
else{
j=max(,p-i+);
while(i+j<lens&&j<lent&&s[i+j]==t[j])j++;
ext[i]=j;
k=i;
}
}
}

字符串匹配--扩展KMP模板的更多相关文章

  1. 字符串匹配 扩展KMP BM&Sunday

    复杂度都是O(n) 扩展1:BM算法 KMP的匹配是从模式串的开头开始匹配的,而1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹 ...

  2. P3375 【模板】KMP字符串匹配 (KMP模板)

    题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如果你不知道这是什么意思也不要问,去百度 ...

  3. Luogu 3375 【模板】KMP字符串匹配(KMP算法)

    Luogu 3375 [模板]KMP字符串匹配(KMP算法) Description 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来 ...

  4. 字符串匹配的 KMP算法

    一般字符串匹配过程 KMP算法是字符串匹配算法的一种改进版,一般的字符串匹配算法是:从主串(目标字符串)和模式串(待匹配字符串)的第一个字符开始比较,如果相等则继续匹配下一个字符, 如果不相等则从主串 ...

  5. 字符串匹配的kmp算法 及 python实现

    一:背景 给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题. Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的常 ...

  6. HDU 2087 剪花布条(字符串匹配,KMP)

    HDU 2087 剪花布条(字符串匹配,KMP) Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出 ...

  7. HDU 1686 Oulipo / POJ 3461 Oulipo / SCU 2652 Oulipo (字符串匹配,KMP)

    HDU 1686 Oulipo / POJ 3461 Oulipo / SCU 2652 Oulipo (字符串匹配,KMP) Description The French author George ...

  8. HDU 1711 Number Sequence (字符串匹配,KMP算法)

    HDU 1711 Number Sequence (字符串匹配,KMP算法) Description Given two sequences of numbers : a1, a2, ...... , ...

  9. kmp模板 && 扩展kmp模板

    kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...

随机推荐

  1. js和css兼容问题

    (一)html部分 1.H5新标签在IE9以下的浏览器识别 <!--[if lt IE 9]>  <script type="text/javascript" s ...

  2. Myeclipse2016安装Aptana

    Myeclipse2016安装Aptana 想装个Aptana,装了半天,网上说的什么links方式啊,在线方式啊,都是什么的浮云. 所以自己来写个安装教程. 一.Aptana简要介绍 Aptana有 ...

  3. Windows 2008 更改网卡绑定顺序

    用 ncpa.cpl 或者用鼠标右键点网上邻居进去也好. 来到网卡列表画面. 然后,你会发觉没有菜单去操作[高级设置], 这里,最高级的步骤来了, 就是你需要按一个 [Alt]把菜单给显示出来,太神奇 ...

  4. 微服务设计 - api版本控制

    要描述了几种API版本控制的方法.用户可以查询原始的API,或者添加定制的头文件来接收特定的版本.如果应用程序收到一个重大修订,将URI修改为V2.在进行迭代改进时,将创建与更改日期相一致的端点,并允 ...

  5. [Java学习] Java super关键字

    super 关键字与 this 类似,this 用来表示当前类的实例,super 用来表示父类. super 可以用在子类中,通过点号(.)来获取父类的成员变量和方法.super 也可以用在子类的子类 ...

  6. English trip -- VC(情景课)9 B Outside chores 室外家务

    Vocabulary focus 核心词汇 cutting the grass 修剪草坪 getting the mail  收到邮件 taking out the trash  把垃圾带出去 wal ...

  7. Android之SwipeRefreshLayout下拉刷新组件

    SwipeRefreshLayout概述 SwipeRefrshLayout是Google官方更新的一个Widget,可以实现下拉刷新的效果.该控件集成自ViewGroup在support-v4兼容包 ...

  8. git log 查找

    查找含有某个字符串的 commit git log --grep=224 // 这条命令是查看含有 "224" 关键字的 git commit 查看某个作者 git log --a ...

  9. AI学习路径

  10. hdu-2227-dp+bit

    Find the nondecreasing subsequences Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/3 ...