题目:许多程序会大量使用字符串。对于不同的字符串,我们希望能够有办法判断其相似程度。我们定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:
1. 修改一个字符(如把“a”替换为“b”)。
2. 增加一个字符(如把“abdd”变为“aebdd”)。
3. 删除一个字符(如把“travelling”变为“traveling”)。
比如,对于“abcdefg”和“abcdef”两个字符串来说, 我们认为可以通过增加/减少一个“g”的方式来达到目的。上面的两种方案,都仅需要一次操作。把这个操作所需要的次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数。也就是说,“abcdefg”和“abcdef”的距离为1,相似度为1 / 2 = 0.5。
给定任意两个字符串,你是否能写出一个算法来计算出它们的相似度呢?
解法:在这个题目中,我们并不在乎两个字符串变得相等之后的字符串是怎样的。所以
1. 一步操作之后,再计算A[2, …, lenA]和B[1, …, lenB]的距离。
2. 一步操作之后,再计算A[1, …, lenA]和B[2, …, lenB]的距离。
3. 一步操作之后,再计算A[2, …, lenA]和B[2, …, lenB]的距离。
这样,很快就可以完成一个递归程序:
/* 计算字符串最小距离 */ #include <stdio.h> #include <stdlib.h> #include <string.h> char *s1="abcdef"; char *s2="aecdedf"; int minvalue(int d1,int d2,int d3) { int min; min=d1; if(d2<min) { min=d2; } if(d3<min) { min=d3; } return min; } int CalculateStringDistance(char s1[],int b1,int e1,char s2[],int b2,int e2) { int d1,d2,d3; if(b1>e1) //串s1比较完毕 { return e2-b2+1; } if(b2>e2) //串s2比较完毕 { return e1-b1+1; } if(s1[b1]==s2[b2]) //当前字母相同,后移一个字母对于余串进行比较 { CalculateStringDistance(s1,b1+1,e1,s2,b2+1,e2); } else { d1=CalculateStringDistance(s1,b1,e1,s2,b2+1,e2); //等价于删除串s2首字母 d2=CalculateStringDistance(s1,b1+1,e1,s2,b2,e2); //等价于删除串s1首字母 d3=CalculateStringDistance(s1,b1+1,e1,s2,b2+1,e2); //等价于删除串s1和串s2的首字母 return minvalue(d1,d2,d3)+1; //由于删除操作距离增加1 } } int main(void) { int dis,len1,len2; len1=strlen(s1); len2=strlen(s2); dis=CalculateStringDistance(s1,0,len1-1,s2,0,len2-1); printf("The distance between \n\"%s\"\n and\n\"%s\"\nis %d.\n\n",s1,s2,dis); system("pause"); return 0; }