数据结构——串的朴素模式和KMP匹配算法

一、朴素模式

假设我们要从主串S=”goodgoogle"中找到子串T=“google"的位置,步骤如下:

i表示主串的当前位置下标,j表示子串的当前位置下标,如上图在第一轮比较(i=1开始)中j=4和i=4的位置不匹配,接下来就要指针回退,从i=2开始比较,如下:

如此反复直到比较到 i =(主串长度-子串长度+1)的位置或者 j = 子串的长度 就退出比较循环,上面的主串和子串在比较到i=5的位置就完全匹配了。

#include <stdio.h>

int Index(const char S[], const char T[], int pos){
	int i = pos; //主串当前下标
	int j = 1;	 //子串当前下标
	//S[0]是主串的长度,T[0]是子串的长度
	while(i <= S[0] && j <= T[0]){
		//如果相等则继续向下比较
		if(S[i] == T[j]) {
			++i;
			++j;
		//如果不等则指针回退
		}else{
			i = i - j + 2; //主串回退
			j = 1;
		}
	}
	//j>T[0]则说明子串被完全匹配
	if( j > T[0]) return i - T[0];
	else return 0;
}

int main(){
	char S[] = {10, ‘g‘, ‘o‘, ‘o‘, ‘d‘, ‘g‘, ‘o‘, ‘o‘,
		‘g‘, ‘l‘, ‘e‘};
	char T[] = {6, ‘g‘, ‘o‘, ‘o‘, ‘g‘, ‘l‘, ‘e‘};
	int i =	Index(S, T, 1);
	printf("%d\n", i);

	return 0;
}

分析一下这种匹配算法最好的情况时间复杂度是O(1)只需要一次比较,最坏的情况是每次最后一个字符不匹配,时间复杂度是O(m*n) m是主串长度n是子串的长度。

二、KMP算法

像二进制这样的多个0和1重复的字符串,上面的模式匹配需要挨个遍历是非常慢的,KMP算法可以大大避免重复遍历的情况。

下面我们来看看KMP算法的基本原理

如上,可以看到主串S和子串T在第一轮比较的时候,前面5个相等,只有i=6和j=6的位置不等。由于子串T中abcde这5个字符本身互不相等,可以知道子串T中a就不可能和j=2、3、4、5的位置的字符相等。所以可以直接跳到i=6的位置进行比较。

再看上图,如果子串T中存在重复的元素(比如j=1,2和j=4,5处的字符),按照上面的分析,我们可以直接跳到i=4的位置比较,但是我们已经知道j=1,2和j=4,5相等,并且i=4,5和j=4,5相等,所以可以不用比较i=4,5和j=1,2。

KMP模式匹配算法就是为了不让i指针回退,既然i值不回退,我们就要考虑变化j的值了。通过上面的观察可以发现,j值的变化与主串其实没有什么关系,而是取决于子串T中是否有重复问题。

我们把T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度,可以得到下面函数:

#include <stdio.h>

void get_next(const char T[], int *next){

	int i,j;
	i = 1;
	j = 0;
	next[1] = 0;
	//T[0]是子串T的长度
	while(i < T[0]){
		//T[i]表示后缀的单个字符
		//T[j]表示前缀的单个字符
		if( j==0 || T[i] == T[j]){
			++i;
			++j;
			next[i] = j;
		}else{
			j = next[j];
		}
	}
}

int Index_KMP(const char S[], const char T[], int pos){
	int i = pos;
	int j = 1;
	int next[255];
	get_next(T, next);

	while(i <= S[0] && j <= T[0]){
		//相对于朴素算法,增加了一个j==0的判断
		if( j==0 || S[i] == T[j]){
			++i;
			++j;
		}else{
			//j回退到合适的位置,i的值不变
			j = next[j];
		}
	}
	if( j>T[0]){
		return i-T[0];
	}else{
		return 0;
	}
}
int main(){

	return 0;
}
时间: 2024-08-28 18:48:59

数据结构——串的朴素模式和KMP匹配算法的相关文章

图解字符串的朴素模式匹配算法

复习串的朴素模式匹配算法 模式匹配 : 子串定位运算,在主串中找出子串出现的位置. 在串匹配中,将主串 S 称为目标(串),子串 T 称为模式(串).如果在主串 S 中能够找到子串 T, 则称匹配成功,返回 第一个 和 子串 T 中 第一个字符 相等 的 字符 在主串 S 中的 序号,否则,称匹配失败,返回 0. 算法思想: 从主串 S 的第 pos 个字符起和模式 T 的第一个字符比较之,若相同,则两者顺次的去比较后续的每一个字符,否则从主串 S 的下一个字符起再重新和模式 T 的字符比较之.

字符串模式匹配算法之一:朴素模式匹配算法

被搜索的字符串称为主串,待搜索的字符串称为模式串.朴素模式匹配算法的基本思想: 对主串的每一个字符作为子串开头,与模式串进行匹配.对主串做大循环,每个字符开头做模式串长度的小循环,直到匹配成功或全部遍历完成为止. 代码实现非常简单: int strStr(char *haystack, char *needle) { for (int i = 0; ; ++i) { for (int j = 0; ; ++j) { if (!needle[j]) return i; if (!haystack[

4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第4章  串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceString.c        相关测试数据下载

串的匹配:朴素匹配&amp;amp;KMP算法

引言 字符串的模式匹配是一种经常使用的操作. 模式匹配(pattern matching),简单讲就是在文本(text,或者说母串str)中寻找一给定的模式(pattern).通常文本都非常大.而模式则比較短小.典型的样例如文本编辑和DNA分析. 在进行文本编辑时,文本一般是一段话或一篇文章,而模式则经常是一个单词.若是对某个指定单词进行替换操作,则要在整篇文章中进行匹配,效率要求肯定是非常高的. 模式匹配的朴素算法 最简单也最easy想到的是朴素匹配.何为朴素匹配,简单讲就是把模式串跟母串从左

串的应用(数组模拟):KMP匹配算法

1 ////////////////////////////////////////////////////////// 2 // String.cpp 3 // 4 // author:Leetao 5 ////////////////////////////////////////////////////////// 6 // 简介: 7 // 串的应用(数组模拟):KMP匹配算法 8 /////////////////////////////////////////////////////

4种字符串匹配算法:BS朴素 Rabin-karp 有限自动机 KMP(中)

接着上文(地址),我们来聊一聊自动机算法(有限自动机字符串匹配算法)和KMP算法. ====#=有限自动机算法=#===== 关于有限自动机,网上的分析的资源,大部分都很笼统,算导上的知识点,全是数学公式,看的也会特别累.因此,打算从算导的第一题开始讲起.从习题入手,讲这个算法的思想. 例子:对模式 P = aabab构造出相应的字符串匹配自动机,并说明它在文本字符串T=aaababaabaababaab上的操作过程. 再讲这个例子之前,我们有必要先来了解一下自动机是什么意思? 有限自动机是什么

实现顺序串的各种模式匹配算法

目的:掌握串的模式匹配算法(BF和KMP )设计 内容:编写一个程序exp4-3.cpp,实现顺序串的各种模式匹配运算,并在此基础上完成以下功能: 1.建立目标串s="abcabcdabcdeabcdefabcdefg"和模式串t="abcdeabcdefab": 2.采用简单匹配算法求t在s中的位置: 3.由模式串t求next数组值和nextval数组值: 4.采用KMP算法求t在s中的位置: 5.采用改进的KMP算法求t在s中的位置: 写在前面 今天学习了如何对

学习日志---串的匹配模式(BF和KMP)

Brute-Force: 其基本思路是:从目标串s="s0s1-sn-1"的第一个字符开始和模式串t="t0t1-tm-1"中的第一个字符比较,若相等,则继续逐个比较后续字符,否则,从目标串s的第2个字符开始重新与模式串t的第一个字符进行比较,依次类推,若从目标串s的第i个字符开始,每个字符依次和模式串t中的对应字符相等,则匹配成功,该算法返回i;否则匹配失败,返回-1. //Brute-Force算法 public class BruteForce {    pu

数据结构——串的相关算法实现

数据结构--串的相关算法实现 顺序串的插入函数实现 在进行顺序串的插入时,插入pos将串分为两个部分(假设为A.B,长度为LA.LB)及待插入部分(假设为C,长度为LC),则串由插入前的AB变为ACB,由于是顺序串,插入会引起元素的移动.可能会出现以下的三种情况: ①插入后串长度(LA+LC+LB)<=MAXLEN,则将B后移LC个元素位置,再将C插入: ②插入后串长度 >=MAXLEN 且 pos+LC <=MAXLEN,则 B 后移时会有部分字符被舍弃; ③插入后串长度>MAX