首页 > 代码库 > 模式匹配的KMP 算法

模式匹配的KMP 算法


常见的字符串匹配时,模式串长度为n,源串长度为m,则从头匹配,两个指针i指向源串,j指向模式串,如遇到不同则回溯使j=0,这样就要重复匹配会使效率变低。

由于在现在i之前 的模式串与匹配串的匹配是相同的,即回溯时,不用将模式串与源串进行匹配,而只将模式串与自身匹配即可得到其是否需要回溯以及回溯到何处。则我们可以在进行模式匹配之前,想对模式串进行自我匹配,来计算出对于i在模式串的任意位置匹配失败后回溯的位置。

而对于自身匹配的算法还有一个优化的地方在于,模式串在b位置匹配到自身的a位置,然后判断一下这两个位置的字符是否相同,如果相同,则将a位置的回溯位置赋值给b,如果不同,则说明没有必要回溯到这个位置,因为回溯后不匹配,则直接将其置为0,表示从0开始重新匹配、

失败函数的返回值为-1是用来设置其结构,使其能够在自我匹配时简单实现其功能,标识匹配失败重新开始,但其在模式匹配中效果与0相同,都是i置为0,j++,然后继续匹配。

自我匹配放在一个失败函数中,对模式字符串进行操作,然后将结果放在一个数组中方便查询。

试着写出c++代码:


这里每次遍历时,是判断第i个字符串如果相同,那么第i加一个字符串不符就要返回的位置,每次都是对i+1进行操作,所以最后一次会对数组中下标为n的字符进行操作,会越界,则之前建fail数组时,要考虑一下。



void FailString(int f[],const char* str){
	int length = strlen(str);
	int i =0, k = -1;
	f[0] = -1;
	while( i < length){
		if(k == -1 || str[i] == str[k]){
			i++;k++;
			if(str[i] == str[k])
				f[i] = f[k];
			else
				f[i] = k;


		}else
			k = f[k];
	}
}
bool compareString(const char* charA,const char* charB){
	if( charA == 0 || charB == 0)
		return false;
	int Alen = strlen(charA);
	int Blen = strlen(charB);
	if( ! Alen || ! Blen )
		return false;
	if( Blen > Alen)return false;
	int* fail = new int[ Blen+1 ];
	FailString(fail,charB);
	int i = 0 , j = 0;
	while(i < Alen && j < Blen){
		if( charA[i] != charB[j] ){
			if(fail[i] == -1 )
				j = 0;
			else
				j = fail[i];
		}else
			j ++;
		i++;
	}
	delete[] fail;
	fail =NULL ;
	return j==Blen;
}

void main(){
	char* s1 = "abcabcaabcabbac";
	char* s2 = "abcabcabbac";
	if(compareString(s1,s2))
		cout<<"s1==s2"<<endl;
	cin.get();


}


模式匹配的KMP 算法