字符串匹配--拓展KMP模板

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

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

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

 1 void EKMP(char s[],char t[],int lens,int lent){    //s为字母串,t为子串,并分别传入两串长度,ekmp是求t串与s串每个位置开头的最长公共前缀
 2     int i,j,p,l,k;
 3     nxt[0]=lent;j=0;    //t串自匹配,从t0开始的t的子串(即t串本身)与t串的最长公共前缀定为t串长度,j为已匹配完的位置,j+1即待匹配的位置
 4     while(j+1<lent&&t[j]==t[j+1])j++;    //先匹配t1开始的子串,若依次匹配直到失配
 5     nxt[1]=j;    //t1开始的子串与t串最长公共前缀长度即为j
 6     k=1;    //k为除t0外的最远匹配的开始字符,后续每次进行额外匹配就更新它
 7     for(i=2;i<lent;i++){    //i表示匹配从ti开始的子串与t串的最长公共前缀
 8         p=nxt[k]+k-1;    //p即为k所对应的最远失配位置,也是整个t串在自匹配过程中已经匹配到的位置
 9         l=nxt[i-k];
10         if(i+l<p+1)nxt[i]=l;    //从ti开始已经确定匹配成功的结束位置与总匹配过的位置p比较,若结束位置小,则说明到i+l出已经失配,ti开始的最长公共前缀即为l,否则对超过p的部分进行匹配,直到失配并更新k
11         else{
12             j=max(0,p-i+1);
13             while(i+j<lent&&t[i+j]==t[j])j++;
14             nxt[i]=j;
15             k=i;
16         }
17     }
18
19     j=0;    //t与s的每个子串匹配,可以根据之前已经匹配过的s串的部分转化为t串与s中t的子串匹配,首先初始匹配位置赋为0
20     while(j<lens&&j<lent&&s[j]==t[j])j++;    //先匹配s0开始的串和t串的最长公共前缀
21     ext[0]=j;k=0;    //s0处的最长公共前缀即刚匹配完的j,将最长匹配到的位置对应的s0赋给k,之后进行与t串自匹配基本一样的操作,但是循环的从i=1开始,更新ext数组
22     for(i=1;i<lens;i++){
23         p=ext[k]+k-1;
24         l=nxt[i-k];
25         if(l+i<p+1)ext[i]=l;
26         else{
27             j=max(0,p-i+1);
28             while(i+j<lens&&j<lent&&s[i+j]==t[j])j++;
29             ext[i]=j;
30             k=i;
31         }
32     }
33 }

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

 1 void EKMP(char s[],char t[],int lens,int lent){
 2     int i,j,p,l,k;
 3     nxt[0]=lent;j=0;
 4     while(j+1<lent&&t[j]==t[j+1])j++;
 5     nxt[1]=j;
 6     k=1;
 7     for(i=2;i<lent;i++){
 8         p=nxt[k]+k-1;
 9         l=nxt[i-k];
10         if(i+l<p+1)nxt[i]=l;
11         else{
12             j=max(0,p-i+1);
13             while(i+j<lent&&t[i+j]==t[j])j++;
14             nxt[i]=j;
15             k=i;
16         }
17     }
18
19     j=0;
20     while(j<lens&&j<lent&&s[j]==t[j])j++;
21     ext[0]=j;k=0;
22     for(i=1;i<lens;i++){
23         p=ext[k]+k-1;
24         l=nxt[i-k];
25         if(l+i<p+1)ext[i]=l;
26         else{
27             j=max(0,p-i+1);
28             while(i+j<lens&&j<lent&&s[i+j]==t[j])j++;
29             ext[i]=j;
30             k=i;
31         }
32     }
33 }
时间: 2024-10-09 13:47:38

字符串匹配--拓展KMP模板的相关文章

字符串匹配的KMP算法

html, body { font-size: 15px; } body { font-family: Helvetica, "Hiragino Sans GB", 微软雅黑, "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.6; color: ; background-color: ; margin: 0; padding: 16px 20px; } h1, h2, h

[算法系列之二十六]字符串匹配之KMP算法

一 简介 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 二 基于部分匹配表的KMP算法 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含搜索串"ABCDABD"? 步骤1:字符串"BBC ABC

字符串匹配(KMP 算法 含代码)

主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知识 串(string或字符串)是由零个或多个字符组成的有限序列,一般记为 当中s是串的名,用单引號括起来的字符序列是串的值:ai(1<=i<=n)能够是字母.数值或其它字符.串中字符的数组 n称为串的长度.零个字符的串称为空串,它的长度为0 串中随意个连续的字符组成的子序列称为该串的子串. 包括子

字符串匹配与KMP算法笔记

>>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个一个进行比较, 如果不成功则模式串向右移动一个单位,直到匹配成功或者到达匹配串最后仍然不成功,返回失败. 很明显,这种算法有很多的地方可以优化,假设要搜索的串为S,长度为n,要匹配的串为M,长度为m,时间复杂度为O(nm). >>KMP算法 Knuth-Morris-Pratt算法以三个发明者命名

字符串匹配 【kmp】

字符串匹配 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 214 Solved: 81 Description 给你两个字符串A,B,请输出B字符串在A字符串中出现了几次. Input 多组测试数据,每组输入两个字符串.字符串的长度 <= 1000000. Output 输出B在A中出现的次数. Sample Input aaa aa Sample Output 1 子串在母串中出现的次数,串不重叠 #include <stdio.h> #

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

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth. 这种算法不太容易理解,网上有很多解释,但读起来都很费劲.直到读到Jake Boxer的文章,我才真正理解这种算法.下面,我用自己的语言

数据结构之 字符串---字符串匹配(kmp算法)

串结构练习——字符串匹配 Time Limit: 1000MS Memory limit: 65536K 题目描述 给定两个字符串string1和string2,判断string2是否为string1的子串. 输入 输入包含多组数据,每组测试数据包含两行,第一行代表string1,第二行代表string2,string1和string2中保证不出现空格. 输出 对于每组输入数据,若string2是string1的子串,则输出"YES",否则输出"NO". 示例输入

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

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth. 这种算法不太容易理解,网上有很多解释,但读起来都很费劲.直到读到Jake Boxer的文章,我才真正理解这种算法.下面,我用自己的语言

[转] 字符串匹配的KMP算法

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth. 这种算法不太容易理解,网上有很多解释,但读起来都很费劲.直到读到Jake Boxer的文章,我才真正理解这种算法.下面,我用自己的语言