串的模式匹配算法

今天复习数据结构,发现自己之前忽视了很久的一个算法,关于求串的匹配算法。这里有两种解决办法。

其一是常规解决思路对串进行挨个匹配,若以i指向主串,j指向匹配串,则在匹配过程中需要不停的回溯i指针,假设T={ababcabababab} S={ababa}

我们可以发现该算法在匹配时,一旦遇见不匹配的情况指针i就会回溯,同时产生了大量不需要的匹配过程。尤其是当遇见如T={AAAAAAAAAAAAAAAAAAAAAAB} S={AAAB}这类情况时时间复杂度为O(n*m)

代码实现

方法二KMP

这种改进算法是由D.E.Knuth与VR.Pratt和J.H.Morris同时发现的,因此人人们称它为克努特-莫里斯-普拉特操作(简称KMP算法)。此算法可以在O(n+m)的时间数量级上完成串的模式匹配操作。其改进在于:每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。这是书上的解释、、、谁tm能看懂

这里的尽可能远的意思时,我们拿模式串和主串进行比对时对于i指针,即指向主串的指针不会产生回溯,通过移动模式来匹配下面举例说明

在第一趟匹配的过程中我们发现当i = 2时匹配失败,此时j = 2;按照我们刚才说的对模式进行移动,至于移动的多少可以看这里模式对应的next表。这里先给出next表,接下来会解释next的来历现在只要知道怎么用就好了。next = {0,0,1,1,2,0,1,0}当j = 2时匹配失败我们需要找到模式的偏移量,对应着表中的第j-1个元素我们发现其值为零那么就将模式向左移一位,即j = 1;

在第二趟匹配中,当i = 2,j = 1时匹配失败,模式左移一位;

第三趟匹配中,i = 8, j = 6匹配失败,对照着表第j-1个元素值为2将模式左移3位,即j = 3;

第四趟匹配全部完成。

那么为什么要这么移动?next的值究竟代表着什么?

先给大家介绍前缀码和后缀码拿模式来讲 S={abaabca}

子串

a 没有前缀码和后缀码

ab 前缀码a,后缀码b

aba 前缀码{a,ab}后缀码{ba,b}

abaa 前缀码{a,ab,aba}后缀码{baa,aa,a}

abaab 前缀码{a,ab,aba,abaa} 后缀码{b,ab,aab,baab}

abaabca 前缀码{a,ab,aba.abaa,abaab,abaac} 后缀码{a,ca,bca,abca,aabca,baabca}

next表中存储的值即为当前子串中公共前后缀码的长度,比如aba 前后缀码没有相同的所以next[2]=0(ps:这里是从零开始的数组) abaa 前后缀码有一个相同a 所以next[3] = 1;以此类推得到next表;

那么我们为什么求得next表?

next的表存储的是当前子串的公共前后缀码个数(k),意味着next[i]=k意味着S[0...k-1] = S[i-k+1] {abaab里面 前面的ab与后面的ab}这里很重要!!!!!!这里意味着如果我们当前已经匹配完成的字符里已经包含到了abaab,这里假设pos指向主串,j指向模式; 那么就有T[pos-j......pos-1]==S[0....j-1],并且T[pos-2,pos-1] == a,b S[0,1]==a,b;这两个值相同的!!!!!我们看一下是怎么来的由于T[pos-j...pos-1]==S[0...j-1] 得到①T[pos-j,pos-j+1] == S[0,1]==a,b; ②T[pos-2,pos-1] == S[j-2,j-1]  ③S[0,1]==S[j-2,j-1];由①②③可以得到 T[pos-2,pos-1] == a,b S[0,1]==a,b,我们得到结论不需要再去关注S[0,1]只需要关注S[2]与T[pos]这样我们的的pos指针就不需要回溯。还记得我们的next表吗?abaab对应的next[4] = 2; 即告诉我们前两个字符不需要在进行匹配直接从第三个字符开始匹配。大家可以对应例子中的第三趟进行验证。

我们已经知道了next表的用法,他的存在能帮我们有效的减少不必要的校对,那么剩下的问题是我们怎么求得next表呢?next表的求取方法是整个KMP方法的难点。

我们知道next表中存储的是当前字符串的最长公共前后缀码的个数。有这样的关系 S[i+1]==S[j+1] next[j+1] = next[j]+1; 但是遇见 S[i+1]!=S[j+1]时 next[j+1]的值我们怎么求呢?

求next的重点就在这里 与前面利用next[]进行匹配的思路一样我们发现next[j]的值代表S[0..j]这个字符串中最大公共前后缀码,设next[j]  = k;那么就有S[j-k+1....j]==S[0..k-1]。现在已经知道S[i+1] != S[j+1]了,那么我们下一步就是缩短S[j+1]前缀码的范围再尝试去匹配。这里就有k = next[k-1]!!!!!!!!重点就在这里由S[j-k+1....j]==S[0..k-1]得知S[k-1]==S[j];接下来就是对比S[j]与S[k]按照上面的顺序进行匹配;

时间: 2024-10-23 12:45:09

串的模式匹配算法的相关文章

第四章:2.串 -- 串的模式匹配算法(KMP)

前言: 目录: 1.串类型的定义 2.串的表示和实现 3.串的模式匹配算法 4.串操作应用举例 正文: 串的模式匹配即,在给定主串S 中,搜索子串T 的位置,如果存在T 则返回其所在位置,否则返回 0 串的模式匹配算法 主串 S: a b c a b c d s v t 子串 T: a b c d 一.原始算法 匹配一旦失败,子串即向右移动一个单位,直到完全匹配停止. 第一次匹配:(注:红色代表不匹配(失配)) S: a b c a b c a b c d s v t   T: a b c d

串的模式匹配算法(KMP)

算法: #include<IOSTREAM> using namespace std; #define MAXSIZE 100 void calNext(const char *T,int *next);//T为模式串,next为预判数组 int kmp_match(const char *S,const char *T);//在主串S中寻找模式串T,如果找到返回其位置,否则返回-1.位置从0开始 void calNext(const char *T,int *next) { int n =

24、蛤蟆的数据结构笔记之二十四串的模式匹配算法

24.蛤蟆的数据结构笔记之二十四串的模式匹配算法 本篇名言:"燧石受到的敲打越厉害,发出的光就越灿烂. -- 马克思" 来看下两个算法,BF和KMP算法在串的模式匹配中实现. 欢迎转载,转载请标明出处: 1.  BF算法 BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符:若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果.B

串的模式匹配算法(BF算法和KMP算法)

串的模式匹配算法 子串的定位操作通常称为串的 模式匹配,其中T称为 模式串. 一般的求子串位置的定位函数(Brute Force) 我写java的代码是这样的 int index(String S,String T,int pos){ char[] s_arr = S.toCharArray(); char[] t_arr = T.toCharArray(); int i,j,k;//i是主串S的指针,j是模式串的指针 if(pos < 0 || pos>S.length() || S.len

《数据结构》之串的模式匹配算法——KMP算法

1 //串的模式匹配算法 2 //KMP算法,时间复杂度为O(n+m) 3 #include <iostream> 4 #include <string> 5 #include <cstring> 6 using namespace std; 7 8 //-----串的定长顺序存储结构----- 9 #define MAXLEN 255 //串的最大长度 10 typedef struct { 11 char ch[MAXLEN + 1]; //存储串的一维数组 12

串、串的模式匹配算法(子串查找)BF算法、KMP算法

串的定长顺序存储#define MAXSTRLEN 255,//超出这个长度则超出部分被舍去,称为截断 串的模式匹配: 串的定义:0个或多个字符组成的有限序列S = 'a1a2a3--.an ' n = 0时为空串串的顺序存储结构:字符数组,串的长度就是数组末尾'\0'前面的字符个数数组需在定义时确定长度,有局限性数组的最大长度二:串的堆分配存储表示typedef struct { char *ch; //若是非空串,则按串长分配存储区 //否则ch为空 int length; //串长度}HS

4.2 串的模式匹配算法

<?php header("content-type:text/html;charset=utf-8"); class Linear_string{ /** * 串模式匹配算法 * *包括 * 1.串的初始化 __contruct() * 2.朴素的模式匹配算法 index() * 3.KMP模式匹配算法 * 4.改进的KMP模式匹配算法 */ private $string; private $length; //构造函数 public function __construct

串-KMP模式匹配算法(nextval数组)

#include <stdio.h> #include <stdlib.h> #include <string.h> void get_next(char T[100],int *next); int Index_KMP(char S[100],char T[100],int pos); int main() { int n; char S[100],T[100]; gets(S); gets(T); n=Index_KMP(S,T,2); printf("%

数据结构- 串的模式匹配算法:BF和 KMP算法

Brute-Force算法的思想 1.BF(Brute-Force)算法 Brute-Force算法的基本思想是: 1) 从目标串s 的第一个字符起和模式串t的第一个字符进行比较,若相等,则继续逐个比较后续字符,否则从串s 的第二个字符起再重新和串t进行比较. 2) 依此类推,直至串t 中的每个字符依次和串s的一个连续的字符序列相等,则称模式匹配成功,此时串t的第一个字符在串s 中的位置就是t 在s中的位置,否则模式匹配不成功. Brute-Force算法的实现 c语言实现: [cpp] vie

【数据结构】1、串的模式匹配算法

首先我们一般求子串的位置的时候,我们可以使用这样的方法 /* *功能:这个是定长的串的顺序存储 *时间:2015年7月15日17:16:01 *文件:SString.h *作者:cutter_point */ #ifndef SSTRING_H #define SSTRING_H #define MAXSTRLEN 255 class SString { unsigned char* ch; //我们的串的顺序存储空间 unsigned int length; //我们有效元素的个数 publi