串的模式匹配算法

串的模式匹配算法

子串的定位操作通常称作串的模式匹配。通常用函数Index( S, T, pos)来求解,其中S为主串,T为模式串,pos为主串中的位置,整个函数的作用是返回在字符串S中的第pos个字符及以后(包含pos)首次出现与字符串T相匹配的子串的第一个字符的位置。例如:S=”abciu(5)abcjka(11)bcdiii”,T=”abcd”,则S中第5个字符后首次出现与T相同的子串的位置为11。

用计数指针i和j分别指示主串S和模式串T中当前正待比较的字符位置对应的下标(注意字符串的第n个字符对应的下标为n-1,故i的初始值为pos-1,j 的初始值为0,因此j 的值即为匹配的字符的个数)。算法的基本思想是:

(1)从主串的S的第i个位置代表的字符起和模式T的第一个字符(对应j = 0)比较,如果相等:

1)则i++,j++继续逐个比较后续字符;

2)当有n个(n大于1且小于模式T的长度)字符匹配,第n+1个字符不匹配时,用主串中这n个匹配的连续字符的第二个字符作为当前的新i值(当前的新i值与之前的旧i值的关系为inew= iold –n +1,其中iold–n 即为连续匹配的n个字符的第一个字符,再加1即为匹配的第二个字符,而n = j 故inew= iold –j +1)与模式T的第一个字符比较,将n值也置为0,回到(1)继续比较。S=”abciu(4)ab(6)cjka(10)bcdiii”,T=”abcd”,例如对于该字符串,从第六个字符开始的三个字符匹配之后,此时i = 8,j = 3,对应的主串字符为‘j’与模式T的第四个字符d不匹配;因此inew= iold –n +1 = 8 - 3 + 1 =6,j = 0继续回到(1)比较。

(2)从主串的S的第i(第一次比较时i值即为pos的值)个字符起和模式T的第一个字符比较之后不相等,则从主串的下一个字符(i++)起再重新和模式T的第一个字符( j = 1 )比较。

(3)依次类推,直到连续匹配的字符个数n等于模式T的字符个数时,匹配成功,返回这n个连续字符的第一个字符的位置(当前i值减去字符长度n即为首字符的位置)。否则,当S到达字符串末尾时n值不等于模式T的字符个数时,匹配失败。

typedef struct{
	char *ch;
	int length;
}HString;

//若str1指向的主串中存在和str2指向的字符串相同的字串,则返回她在主串S中第pos个字符之后第一次出现的位置
int Index( HString *str1, HString *str2, int pos )
{
	int i = 0;
	int j = 0;
	int k = 0;
	int position[MAX] = { MAX * 0 };  //用于存储出现和str2指向的串相同的子串的开始位置
	

	if( str1->length == 0 || str2->length == 0 ){   //如果两个字符串有一个为空,则报错并返回0
		printf( "Index error:one of the string is empty!\n" );
		return 0;
	}
	else{  //如果均不为空
		while( i < str1->length ){    //循环次数i大于主串的长度时,跳出循环
			if( *( str1->ch + i ) == *( str2->ch + j ) ){   
				if( j == str2->length - 1 ){     //当j值为str2的最后一个字符的下标时,表示str1中存在一个与str2相同的串
					position[k] = i - j + 1;   //第k+1个和str2指向的串相同的子串的开始位置赋给position的第k项
					j = -1;  //将j置零,是的后面自增一后j为0,即从str2的第一项继续开始判断
					k++;
				}
				i++;
				j++;
			}
			else{//如果str2的第j个字符与str1的i个字符不相等,
				if( j == 0 ){   //j等于0说明到目前为止str1中还没有出现与str2的前几个字符匹配的情况
					i++;                           // 则继续对str1的第i+1个字符与str2的第一个字符比较
				}
				else{
					i = i - j + 1;    //j为相同的字符的个数,i - j为str1中与str2的第一个字符匹配的字符,
				}               //下次应该从该字符的下一个位置开始比较,因此加1
				j = 0;//j不等于0说明str2的前j-1个字符与str1的中第i个位置之前的j-1个子符匹配,则继续用str1的第i个字符与str2的第一个字符比较
//比如str1为cdefabcabcd,str2为abcd,第四个字符到第7个字符相等,第八个字符不等,此时i为8,j为4,则下次应用str1的第五个字符b与str2的第一个字符比较

			}
		}
		k = 0;
		while( position[ k ] > 0 ){   //循环开始时k=0,当position的第0项不为0时,说明str1中存在于str2相同的字串
			if( position[k] < pos )  //若position[k]小于pos,说明第k+1个与str2相同的子串出现的位置在pos之前
				k++;                //继续寻找下一个与str2相同的子串出现的位置
			else                  //若position[k]大于等于于pos,说明第k+1个与str2相同的子串出现的位置在pos之后且为第一次出现
				return position[k];  //返回position[k]对应的位置
		}
		return 0;   //在str1的pos之后不存在与str2相同的子串
		
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值