编程之美3.3 计算字符串的相似度(我的失败思路)

题干

许多程序会大量使用字符串。对于不同的字符串,我们希望能够有办法判断其相似程序。我们定义一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:

  1. 修改一个字符(如把“a”替换为“b”);
  2. 增加一个字符(如把“abdd”变为“aebdd”);
  3. 删除一个字符(如把“travelling”变为“traveling”);

比如,对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g”的方式来达到目的。上面的两种方案,都仅需要一 次 。把这个操作所需要的次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数。也就是说,“abcdefg”和“abcdef”的距离为1,相似度 为1/2=0.5。

给定任意两个字符串,你是否能写出一个算法来计算它们的相似度呢?

我的解题思路

  1. 如果两个字符串长度一样,那么只需要统计对应位置不一样的字符串的个数
  2. 如果两个字符串长度不一样,对长的为标准,逐一与短的比较,如果对应字符相同,则长的和短的都往后挪动一下,两者不同,则长的往后移动,短的不移动。

刚开始我以为我对了,直到找到了一种情况我是没有办法解决的,请看下面代码中的注释部分。


代码

 
#include <stdio.h>
#include <string.h>

float getStringSim(char *str1,char *str2){
	int distance=getStringDistance(str1,str2);
	return 1/(distance+1);
}

int getStringDistance(char *str1,char *str2){
	int distance=0;
	int length1=strlen(str1);
	int length2=strlen(str2);
	/*下面三句是防止有字符串为空的情况*/
	if(length1==0&&length2==0) return 0;
	if(length1==0) return length2;
	if(length2==0) return length1;

	char *longStr;
	char *shortStr;

	if(length1==length2){
		longStr=str1;
		shortStr=str2;
		for(;*longStr!='\0';++longStr,++shortStr){
			if(*longStr!=*shortStr) distance++;
		}
		return distance;
	}else if(length1>length2){
		longStr=str1;
		shortStr=str2;
	}else{
		longStr=str2;
		shortStr=str1;
	}

	//下面的代码只有字符串长度两者不相等才会执行
	while(*longStr!='\0'){
		if(*longStr==*shortStr){
			longStr++;
			shortStr++;
			continue;
		}
		distance++;
		longStr++;
	}
	return distance;

}

int main(int argc, char **argv) {
	int distance;

	distance=getStringDistance(" "," ");
	printf(" 和 的距离:%d\n",distance);

	distance=getStringDistance("aaa"," ");
	printf("aaa和 的距离:%d\n",distance);

	distance=getStringDistance(" ","aaa");
	printf(" 和aaa的距离:%d\n",distance);

	distance=getStringDistance("a","b");
	printf("a和b的距离:%d\n",distance);

	distance=getStringDistance("abcd","abcd");
	printf("abcd和abcd的距离:%d\n",distance);

	distance=getStringDistance("abcd","bcda");
	printf("abcd和bcda的距离:%d\n",distance);


	distance=getStringDistance("abcd","bd");
	printf("abcd和bd的距离:%d\n",distance);

	distance=getStringDistance("abdd","aebdd");
	printf("abdd和aebdd的距离:%d\n",distance);

	distance=getStringDistance("travelling","traveling");
	printf("travelling和traveling的距离:%d\n",distance);

	/*当以上测试用列全部正确的时候,我还以为天才般的我发现了什么
	 * 但是下面两个测试用列让我发现我忽略了一种情况
	 * 那就当第一个字母不同,但是第二个字母又相同的情况
	 *
	 * 想了一下,这个按我的思路没有办法解决的,
	 * 因为当第一个不一样的时候,我不知道是是缺少了一个还是替换第一个,
	 * 所以才造成了第一个无法处理
	 */
	distance=getStringDistance("kitten","sitting");
	printf("kitten和sitting的距离:%d\n",distance);

	distance=getStringDistance("abcd","zbd");
	printf("abcd和zbd的距离:%d\n",distance);

}

运行结果

asd@asd-desktop:~/workspace/test/src$ ./a.out 
 和 的距离:0
aaa和 的距离:3
 和aaa的距离:3
a和b的距离:1
abcd和abcd的距离:0
abcd和bcda的距离:4
abcd和zbd的距离:4          注意:错误
abdd和aebdd的距离:1
travelling和traveling的距离:1
kitten和sitting的距离:7    注意:错误
asd@asd-desktop:~/workspace/test/src$ 

进一步阅读

  1. 书后面的答案我认为很完美,因为我自己研究了一遍,所以很轻松就看懂了
  2. 算法导论有整整一章都在讲这个问题,可以参考
  3. 这篇博客讲的也不错,不过KMP算法还真是有点复杂哦 KMP字符串模式匹配详解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值