串的模式匹配-KMP算法

#include<stdio.h>
#include<string.h>
typedef struct String {
	char base[5000];//字符数组
	int nextval[5000];//nextval数组
	int Length=0;
	int HasGottenNext = 0;
}cString;
int KMPFind(cString parent, cString child)
{
	if (!child.HasGottenNext||parent.Length<child.Length)return 0;//在没有求得模式串的next数组的情况下就不能开始搜索匹配
	int i,j;
	for (i = 0, j = 0; i < parent.Length&&j < child.Length;)
	{
		if (parent.base[i] == child.base[j]) { j++; i++; }//相等则二者都移动到下一位
		else {
			if (j == 0) {i++; }//第一位就不相等,整个移动模式串开始比对
			else if(child.nextval[j]!=0){ j = child.nextval[j] - 1; }//利用next数组移动模式串的下标
			else { j = 0; i++; }//遇到不是第一位,但next数组对应值是0的,因为0-1=-1下标不能小于0,所以直接赋给j0,再将模式串整个移动
		}
	}

	if(j>=child.Length)return 1;
	return 0;
}
int BFFind(cString parent, cString child)//蛮力匹配
{
	int i, j;
	for (i = 0; i <= parent.Length-child.Length; i++)
	{
		for (j = 0; j < child.Length; j++)
		{
			if (parent.base[i+j] != child.base[j]) { j = 0; break; }//遇到不相等的就将模式串对比位拨回第一位
		}
		if (j >= child.Length)break;
	}
	if (j >= child.Length)return 1;
	return 0;
}
void SetNextvalArray(cString *Base)
{
	int i,j,n,maxEqual;
	Base->nextval[0] = 0;
	
	**/*Base->nextval[1] = 1;弃
	for (i = 2; i < Base->Length; i++)//依次求每位的next数组值,即求前i位长度子串的最长对称真子串值+1
	{
		n = 0;
		maxEqual = 1;//对称真子串的最长度,初始为1
		while (n<i-1)//不断变化的n长度真子串对比是否相等
		{
			for (j = 0; j <= n; j++)
			{
				if (Base->base[j] != Base->base[i - 1 - (n-j)]) {  break; }//i-1是当前正在求子串的主串的下标范围
			}
			if (j > n)maxEqual = n + 2;//当不跳出的经过for循环说明存在最大长度n+2的子串
			n++;
		}
		Base->nextval[i] = maxEqual;
	} */弃**


	j = 0; i = 1;
	while (i < Base->Length)//获取next数组的关键语句块
	{
		if (j == 0 || Base->base[i-1] == Base->base[j-1])
		{
			i++;
			j++;
			Base->nextval[i-1] = j;
		}
		else j = Base->nextval[j-1];
	}

	char ch;
	for (i = 1; i < Base->Length; i++)//由next数组转为nextval数组
	{
		ch = Base->base[Base->nextval[i]-1];
		if (ch == Base->base[i])Base->nextval[i] = Base->nextval[Base->nextval[i]-1];
	}
	Base->HasGottenNext = 1;//更新状态
	return;
}
void PrintNextvalArray(cString *base)//显示nextval数组的内容
{
	int i;
	if (!base->HasGottenNext)return;
	for (i = 0; i < base->Length; i++)
	{
		printf("%2d",base->nextval[i]);
	}
	printf("\n");
	return;
}
void PrintCharArray(cString *base)//显示串的内容
{
	printf("%s\n", base->base);
	return;
}
void AssignCharArray(cString *Base)
{
	scanf("%s",&Base->base,5000);//获取输入的字符串
	Base->Length = strlen(Base->base);//并赋值给cString的串长度成员变量
	return;
}
int main()
{
	cString Parent, Child;
	AssignCharArray(&Parent);
	AssignCharArray(&Child);
	SetNextvalArray(&Child);
	//PrintNextvalArray(&Child);
	printf("%d\n", KMPFind(Parent, Child));//用KMP算法匹配
	printf("%d\n", BFFind(Parent, Child));//用BF算法匹配
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值