数据结构2.2串的模式匹配

模式匹配

子串在主串中的定位操作称为串的模式匹配,记为index(s,t,pos),即在主串s中,从第pos个字符开始查找与子串t第一次相等的位置。若查找成功,则返回子串t的第一个字符在主串中的位序,否则返回0。其中主串称为目标串,子串称为模式串

Brute-Force算法

基本思想

从目标串的第pos个字符开始与模式串的第一个字符比较,若相等则继续逐个比较后续字符,否则从主串的第pos+1个字符重新和模式串进行比较。以此类推,若存在和模式串相等的子串,则匹配成功返回模式串t的第一个字符在目标串s中的位置;否则,匹配失败返回0。
Brute-Force算法如下

int index(string *s,string *t,int pos){
int i,j;
if(pos < 1 || pos > s->length || pos > s->length - t->length + 1){
return 0;
}//参数非法
i = pos - 1;
i = 0;
while(i < s->length && j < t->length){
	if(s->ch[i] == t->ch[j]){
		i++;
		j++;//继续匹配下一个字符
	}else{
		i = i - j + 1;
		j = 0;//主串、子串指针回溯,重新开始下一次匹配
}
}
if(j >= t->length){
	return i - t->length + 1;//返回主串中已匹配子串的第i个字符的位序
}else{
	return 0;//匹配不成功
}
}

该算法较简单且易于理解,但效率不高,因为目标串指针(i)的回溯消耗了大量时间。

KMP算法

讨论一般情况,设目标串s=“s0 s1 … sn-1”,模式串"t0 t1 … tm-1",当si != tj 时存在
"t0 t1 … tk-1" = “tj-k tj-k+1 … tj-1”(0<k<j)
则下一次比较可以直接从tk与si开始继续下一趟的匹配。若模式串中不存在子串
"t0 t1 … tk-1" = “tj-k tj-k+1 … tj-1”(0<k<j),则下一次比较从t0开始与si继续下一趟匹配。由此可见,k的取值可以由模式串的构成直接得出,与目标串s没有关系。
此时令next[j]=k,则next[j]表明当模式串中第j个字符与目标串中si“失配”时,在模式串中需重新和目标串字符si进行比较的字符位置。

next[j]的实现(修正后)
void getnext(string *t,int next[]){//由模式串t求出next值
int j,k;
j = 0;
k = -1;
next[0] = -1;
while(j < t->length){
	if(k == -1 || t->ch[j] == t->ch[k]){
		if(t->ch[j] != t->ch[k){
			next[j] = k;
		}else{
			next[j] = next[k];
	}else{
k = next[k];
}
}
KMP算法实现
int KMPindex(string *s,string *t,int pos){
int next[INIZSIZE],i,j;
getnext(t,next);
i = pos - 1;
j = 0;
while(i < s->length && j < t->length){
	if(j == -1 || s->ch[i] == t->ch[j]){
	i++;
	j++;
	}else{
	j = next[j];
	}
}
if(j >= t->length){
	return i - t->length + 1;
}else{
return 0;
}
}

猜你喜欢

转载自blog.csdn.net/weixin_43451616/article/details/86475754