字符串(二)——模式匹配(BF与KMP)

(一)BF(Brute Force)——求子串位置的定位函数(普通的模式匹配算法)

int Index(char S[],char T[],int pos){
	//返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数值为0
	//其中,T非空,1<=pos<=StrLength(S) 
	int i=pos,j=1;
	while(i<=S[0]&&j<=T[0]){
		if(S[i]==T[j]){			//继续比较后继字符 
			++i;
			++j;
		}
		else{					//指针后退,重新开始分配 
			i=i-j+2;		//!!!下有附图
			j=1;
		}
		
	}
	if(j>T[0])return i-T[0];
	else 
		return 0;
}

注意:

(1)字符数组的第一个元素存储元素个数length

(2)一般匹配字符串时,我们从目标字符串str(假设长度为n)的第一个下标选取和ptr长度(长度为m)一样的子字符串进行比较,如果一样,就返回开始处的下标值,不一样,选取str下一个下标,同样选取长度为n的字符串进行比较,直到str的末尾(实际比较时,下标移动到n-m)。这样的时间复杂度是O(n*m)。

(3)此算法的最低时间复杂度为 O(n+m),有时这种匹配的效率十分低下,例如:当模式串为‘00000001’时,主串为‘00000000000000000000000000000000000000000000000000001’,由于模式中前7个字符均
为“0”,又因为主串中前52个字符均为“0”,每趟比较模式都在最后一个字符出现不等,此时需将指针i回溯到  i-6  的位置上,并从模式的第一个字符开始重新比较,整个匹配过程中指针 i 需要回溯45次 , 则while循环次数为 46*8*(index*m),可见算法在最坏情况下时间复杂度为O(n*m),这和计算机的存储情况很类似,因为在计算机中,一切数据信息都是以二进制的形式存储的。

(3)匹配过程中的指针回退较难理解,附图如下:


字符串(二)——模式匹配(BF与KMP)_第1张图片


附上完整测试代码:

#include
#include 
#define maxn 100

int Index(char S[],char T[],int pos){
	//返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数值为0
	//其中,T非空,1<=pos<=StrLength(S) 
	int i=pos,j=1;
	while(i<=S[0]&&j<=T[0]){
		if(S[i]==T[j]){			//继续比较后继字符 
			++i;
			++j;
		}
		else{					//指针后退,重新开始分配 
			i=i-j+2;
			j=1;
		}
		
	}
	if(j>T[0])return i-T[0];
	else 
		return 0;
}

print(char s[]){
	for(int i=1;i<=s[0];i++)
		printf("%c",s[i]);
	printf("\n"); 
}

int main(){
	char s1[maxn],s2[maxn];
	int res,pos;
	scanf("%d",&s1[0]);
	for(int i=1;i<=s1[0];i++)
		scanf("%c",&s1[i]);
	print(s1);
	scanf("%d",&s2[0]);
	for(int i=1;i<=s2[0];i++)
		scanf("%c",&s2[i]);
	print(s2);
	res=Index(s1,s2,pos);
	printf("%d\n",res);
	return 0;
} 

如果对字符串的存储实现和基本操作还不太了解的,欢迎戳  字符串(一)——字符串的存储实现与基本操作



你可能感兴趣的:(数据结构)