String pattern matching

Description

字符串的模式匹配是一种常用的运算。所谓模式匹配,可以简单地理解为在目标(字符串)中寻找一个给定的模式(也是字符串),返回目标和模式匹配的第一个子串的首字符位置。通常目标串比较大,而模式串则比较短小

对于字符串较长的模式匹配问题,我们可以使用克努特—莫里斯—普拉特操作(即KMP算法)解决,KMP算法的时间复杂度O(m+n).对于字符串较短的匹配问题,我们也可以使用简单算法解决。请解决如下字符串的模式匹配问题:

给定字符串S与T,规定S上操作REPLACE(i, x)表示为将S中第i个字符更改为x.

求最小操作次数a,使得T为S的子串。当任意次操作均不能使得T为S字串时,输出-1.

Input

两行,共两个字符串,即S、T.

Output

一行,即a的值。

Sample Input

HELLOWORLD

LOWER

Sample Output

1

Hint

保证字符均为英文字母,且S、T长度不超过100.

# include<stdio.h>
# include<string.h>
/*Description
字符串的模式匹配是一种常用的运算。
所谓模式匹配,可以简单地理解为在目标(字符串)中寻找一个给定的模式(也是字符串),
返回目标和模式匹配的第一个子串的首字符位置。通常目标串比较大,而模式串则比较短小。
对于字符串较长的模式匹配问题,我们可以使用克努特—莫里斯—普拉特操作(即KMP算法)解决,
KMP算法的时间复杂度O(m+n).对于字符串较短的匹配问题,我们也可以使用简单算法解决。
请解决如下字符串的模式匹配问题:
给定字符串S与T,规定S上操作REPLACE(i, x)表示为将S中第i个字符更改为x.
求最小操作次数a,使得T为S的子串。当任意次操作均不能使得T为S字串时,输出-1.
Input两行,共两个字符串,即S、T.
Output一行,即a的值。
Sample Input
HELLOWORLD
LOWER
Sample Output
1
Hint
保证字符均为英文字母,且S、T长度不超过100.*/

/*int find(char s[], char t[], int lent, int *p, int lens)
{//思路如下,先假设t与s的字符全不一样,再将t拆分为长度任意的子串与S用strstr匹配
// 如能匹配到,则 这几个字符相同,需要对其他字符(其他字符数目为操作数)进行操作 
	int i = 0, j = 0;
	char temp[100] = {'\0'};//双引号为字符,单引号为字符串 
	for (i = lent - 1;i >= 0; i --)//i从lent-1开始,这样一开始lent-i为1,temp长度为1 
	{
		for (j = 0;j <= i; j ++)//从第j开始取t的子串 
		{//temp长lent-i,即为t的子串 
			strcpy(temp, t + j);//用temp存一段子串(从t+j开始,随着j增加从而遍历) 
			temp[lent - i] = '\0';//在结尾加上截断,获得特定长度的子串 
			//注意下标是从0开始,所以截断为lent-i(字符串长度就是下标最后一个) 
			if ((strstr(s, temp) != 0) && ((strstr(s, temp) - s) + lent -j) <= lens)
			{//若无法匹配到,且 从匹配到的位置开始加上lent-j的长度不超过lens,则可以操作
			//如果 加上lent-j的长度超过lens ,则虽然从匹配到的位置开始加上temp子串长度
			//后不会超过lens,但是 由于要使得s与对t子串后面的部分相同,必须使t子串减去
			//前j个后,从strstr开始,能有s中的元素与之对应 
				*p = i;
			}
		}	
	}	
}
int main()
{
	char s[100] = {'\0'};
	char t[100] = {'\0'};
	scanf("%s %s", &s, &t);
	int lent = strlen(t);//表示长度 
	int lens = strlen(s);//注意,两个记录长度的变量很像,小心别打错了 
	int q;
	int *p = &q;//通过一个指针以便在函数中操作,指针记录操作数 
	*p = lent;//假设t中每个字符都与s不一样,一开始操作lent次 
	if (lent > lens)//无法操作的情况 
	{
		printf("%d\n", -1);
	}
	else
	{
		find(s, t, lent, p,lens);//用find函数确定操作数 
		printf("%d\n", *p);
	}
	
	return 0;
}*/
/*法二法1其实是有问题的,只是碰巧能过。如果t与s相同的部分中间恰好有一个
字母有差异,则由于法一是根据连续的字符判断有多少相同,所以会有很长一段被视为不同 */
	int main (){
	int a,x,y,c,d,i,j,z,m;
	char s[100]={0},t[100]={0},czs[100]={0};
	//思路和法1不同,是把S切为与t等长的子串,遍历比较,得到不同的字符数,取最小值 
	gets(s);
	gets(t);
	x=strlen(s);
	y=strlen(t);
	z=strcmp(s,t);//判断是否完全相同 
	if (y>x)
	{printf("-1\n");}//无法操作的情况 
	else if (z==0)
	{printf("0\n");}//完全相同时 
	else
	{
		for (i=0;i<=x-y;i++)//i用来表示取s子串的首地址,由于s子串长度与t相同为y,故i《=x-y 
		{
			c=0;
			for(j=0;j<y;j++)//j为循环变量 
			{
				if(s[i+j]==t[j]){c++;}//挨个遍历元素进行比较 
			}//c记录 相同字符数目 
		czs[i]=y-c;//记录操作数 
	}
	
	d=czs[0];
	for(m=0;m<=x-y;m++)
	{
		if(czs[m]<d) d=czs[m];//取d为数组的第一个,然后遍历比较,取最小值 
	}
	
	printf("%d\n",d);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值