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;
}