KMP模式匹配算法的一些理解

原创 2012年03月28日 01:05:44

先上代码:

#include <string>
using namespace std;
/****************************KMP模式匹配算法****************************/
void setIndexOfNext(const string &AnalyzeThis, int *Next){//AnalyzeThis, Next从0开始存储有效数据..
	const int Num = AnalyzeThis.size() -  1;
	int preChar = -1, posChar = 0;
	Next[0] = -1;
	while(posChar < Num){
		if(preChar == -1 || AnalyzeThis[preChar] == AnalyzeThis[posChar]){
			++preChar;
			++posChar;
			Next[posChar] = preChar;
		}
		else
			preChar = Next[preChar];	
	}
}

int First_Index_of(const string &Text, const string &Key, int i){//i用来定位Text的字符
	int Next[300];
	int temIndexOfKey = 0;
	setIndexOfNext(Key, Next);
	const int Num_Text = Text.size();
	const int Num_Key = Key.size();
	while(i < Num_Text && temIndexOfKey < Num_Key){
		if(temIndexOfKey == -1 || Text[i] == Key[temIndexOfKey]){
			++i;
			++temIndexOfKey;			
		}
		else
			temIndexOfKey = Next[temIndexOfKey];
	}
	if(temIndexOfKey == Key.size())//结束时i指向符合单词的最后一个字母所在的下标的后一位
		return i - Key.size();
	else
		return -1;
}

/****************************KMP模式匹配算法优化版****************************/
void better_setIndexOfNext(const string &AnalyzeThis, int *Next){//AnalyzeThis, Next从0开始存储有效数据..
	const int Num = AnalyzeThis.size() -  1;
	int preChar = -1, posChar = 0;
	Next[0] = -1;
	while(posChar < Num){
		if(preChar == -1 || AnalyzeThis[preChar] == AnalyzeThis[posChar]){
			++preChar;
			++posChar;
			if(AnalyzeThis[preChar] != AnalyzeThis[posChar])
				Next[posChar] = preChar;
			else
				Next[posChar] = Next[preChar];//再次去掉多余的比较..
		}
		else
			preChar = Next[preChar];	
	}
}

int better_First_Index_of(const string &Text, const string &Key, int i){//i用来定位Text的字符
	int Next[300];
	int temIndexOfKey = 0;
	better_setIndexOfNext(Key, Next);
	const int Num_Text = Text.size();
	const int Num_Key = Key.size();
	while(i < Num_Text && temIndexOfKey < Num_Key){
		if(temIndexOfKey == -1 || Text[i] == Key[temIndexOfKey]){
			++i;
			++temIndexOfKey;			
		}
		else
			temIndexOfKey = Next[temIndexOfKey];
	}
	if(temIndexOfKey == Key.size())//结束时i指向符合单词的最后一个字母所在的下标的后一位
		return i - Key.size();
	else
		return -1;
}

KMP算法的精髓在于:建立匹配串的模式数组(Next[])

1. 什么是Next数组?

传统的字符串匹配采用的是最简单最二逼的迭代,这必然会造成大量不必要的操作,Next数组的存在就是为了去除这些不必要的操作。
每一个Next数组的下标都映射了一个匹配串(AnalyzeThis)中具有相同下标的元素,当这个元素与主串(Text)的某个元素(设为a)不匹配的时候,
Next立功的时候就到了:
它会告诉这个傻逼的电脑,应该继续从匹配串(AnalyzeThis)的哪个元素开始继续与a进行匹配工作。



2. Next数组的建立原理与数值意义

如前文所述,Next充当的是一个指挥着的角色。

这个是Next数组的定义:




(这是第一个元素) ||======================||=(这货就是传说中的第K个元素)===============....(1)
===============================||========================|| =(这个是第J个元素)============....(2)

如上面图所示,这两行表示的是同一串字符,为编译理解我将它表述为两行。其中第一行红色部分指代字符串P1 ...Pk-1
,第二行红色部分指代字符串Pj-k+1......Pj-1, 他俩相等。

相信看到这里大家都清楚了。因为Next[J]被使用的前提是,匹配串(Key)的J元素的前面所有元素都与主串某区域匹配,但主串的a元素与匹配串中K元素不匹配。
即等价于(2)的红色部分(字符串Pj-k+1......Pj-1)与主串相同区域匹配,即等价于(1)中的红色部分(字符串P1 ...Pk-1
与主串的相同区域匹配,又因为这是一个最大的字串(参照上面的MAX定义),所以我只要继续比较匹配串中的K元素与主串中的a元素即可。

Next[J] = K  的原理如上所示~


再来看实现的代码:


while(posChar < Num){
	if(preChar == -1 || AnalyzeThis[preChar] == AnalyzeThis[posChar]){
		++preChar;
		++posChar;
		Next[posChar] = preChar;
	}
	else
		preChar = Next[preChar];
}

这货的主要思想是,1. 将 AnalyzeThis[preChar] == AnalyzeThis[posChar] 的关系表达在第 posChar + 1个元素上,而这种关系又与 posChar + 1上的元素无关!这是一个不断重复的过程..2. 通过 preChar = Next[preChar] 回溯,找到先前一个较短的串,再进行比较..

PS: KMP已经OUT了,但这种算法设计思路相当经典..


KMP模式匹配算法的两点理解

KMP模式匹配算法中,核心就在于next[j]数组的赋值。这里字符串数组均从下标1开始,下标0,用于存储字符串长度。 个人理解,next[j]的值表示,从1到j-1的位置上,有多少个匹配的字符串(包括...
  • liu_qiqi
  • liu_qiqi
  • 2012年12月09日 23:08
  • 258

理解KMP模式匹配算法

我自己开始写的匹配算法,
  • u010913001
  • u010913001
  • 2014年08月31日 10:56
  • 599

KMP 模式匹配算法原理分析

1. KMP算法是一种线性时间复杂的字符串匹配算法,它是对BF算法(Brute-Force,最基本的字符串匹配算法的)改进。     对于给的的原始串S和模式串P,需要从字符串S中找到字符串P出现的...
  • clam_clam
  • clam_clam
  • 2011年09月22日 20:23
  • 4143

串的模式匹配算法——KMP

声明 原文链接:http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm ; 原文的“text”翻译为主串,通常用S表示,...
  • felicitia
  • felicitia
  • 2013年04月18日 17:57
  • 1499

line-height的一些深入理解及应用

“行高”顾名思意指一行文字的高度。具体来说是指两行文字间基线之间的距离。下图的红色线即为基线。一. line-height与line boxes高度ss中起高度作用的应该就是height以及line-...
  • taotaomin99
  • taotaomin99
  • 2017年08月31日 16:51
  • 146

KMP模式匹配算法中next,nextval的分别实现

next数组定义: 对于这个定义,我的理解是从1~j-1中,前缀与后缀有n个相等,则next[j]=n+1。 例如:t="abcabaa" 当j=1时,next[1]=0。 当j=2时,从...
  • huanhuanxiaoxiao
  • huanhuanxiaoxiao
  • 2017年08月09日 11:37
  • 231

理解与实现KMP模式匹配算法

教你理解KMP匹配算法,并提供一种java实现的思路~
  • u014614038
  • u014614038
  • 2015年10月22日 15:48
  • 382

模式匹配KMP算法(Java)

/********查找匹配字符串**********/ //最原始、复杂度最高的做法 //返回childstr在mumstr中第pos个字符之后的位置,如果不存在,则返回0 public int Fi...
  • woliuyunyicai
  • woliuyunyicai
  • 2015年03月25日 15:47
  • 1032

朴素和KMP模式匹配算法(Java)

朴素模式匹配算法 public class Test { //朴素模式匹配算法 public int Index(String s,String t,int pos){ ...
  • scgaliguodong123_
  • scgaliguodong123_
  • 2015年10月18日 15:44
  • 1659

KMP模式匹配算法

在写KMP之前,先把暴力匹配,也就是BF算法先写一下 int BF(string s,string t) { unsigned int i,j; i=j=0; while...
  • q786127150
  • q786127150
  • 2013年10月26日 22:02
  • 405
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:KMP模式匹配算法的一些理解
举报原因:
原因补充:

(最多只允许输入30个字)