标签:style blog http color 使用 os
来自编程之美的一题
许多程序会大量使用字符串。对于不同的字符串,我们希望能够有办法判断其相似程序。我们定义一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:
1.修改一个字符(如把“a”替换为“b”);
2.增加一个字符(如把“abdd”变为“aebdd”);
3.删除一个字符(如把“travelling”变为“traveling”);
比如,对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g”的方式来达到目的。上面的两种方案,都仅需要一 次 。把这个操作所需要的次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数。也就是说,“abcdefg”和“abcdef”的距离为1,相似度 为1/2=0.5。在此我们只需考虑字符串编辑距离即可。
原文的分析与解法
不难看出,两个字符串的距离肯定不超过它们的长度之和(我们可以通过删除操作把两个串都转化为空串)。虽然这个结论对结果没有帮助,但至少可以知道,任意两个字符串的距离都是有限的。
我们还是就住集中考虑如何才能把这个问题转化成规模较小的同样的子问题。如果有两个串A=xabcdae和B=xfdfa,它们的第一个字符是 相同的,只要计算A[2,...,7]=abcdae和B[2,...,5]=fdfa的距离就可以了。但是如果两个串的第一个字符不相同,那么可以进行 如下的操作(lenA和lenB分别是A串和B串的长度)。
1.删除A串的第一个字符,然后计算A[2,...,lenA]和B[1,...,lenB]的距离。
2.删除B串的第一个字符,然后计算A[1,...,lenA]和B[2,...,lenB]的距离。
3.修改A串的第一个字符为B串的第一个字符,然后计算A[2,...,lenA]和B[2,...,lenB]的距离。
4.修改B串的第一个字符为A串的第一个字符,然后计算A[2,...,lenA]和B[2,...,lenB]的距离。
5.增加B串的第一个字符到A串的第一个字符之前,然后计算A[1,...,lenA]和B[2,...,lenB]的距离。
6.增加A串的第一个字符到B串的第一个字符之前,然后计算A[2,...,lenA]和B[1,...,lenB]的距离。
在这个题目中,我们并不在乎两个字符串变得相等之后的字符串是怎样的。所以,可以将上面的6个操作合并为:
1.一步操作之后,再将A[2,...,lenA]和B[1,...,lenB]变成相字符串。
2.一步操作之后,再将A[2,...,lenA]和B[2,...,lenB]变成相字符串。
3.一步操作之后,再将A[1,...,lenA]和B[2,...,lenB]变成相字符串。
如果熟悉动态规划的人很容易就看到这里使用动态规划最好,如果使用递归的话会重复计算很多子问题的。
#include <iostream> using namespace std; const int maxSize = 50; unsigned int dp[maxSize][maxSize]; unsigned int dist(char* s1, int len1, char* s2, int len2){ if(!len1){ return len2; } if(!len2){ return len1; } for(int i = 0; s2[i]; ++i){ dp[0][i+1] = i+1; } for(int i = 0; s1[i]; ++i){ dp[i+1][0] = i+1; } unsigned int t; for(int i = 0; s1[i]; ++i){ for(int j = 0; s2[j]; ++j){ t = ~0; if(s1[i] == s2[j]){ t = dp[i][j]; } else{ if(t > dp[i][j+1]+1){ t = dp[i][j+1]+1; } if(t > dp[i+1][j]+1){ t = dp[i+1][j]+1; } } dp[i+1][j+1] = t; } } return dp[len1][len2]; }
也可参考http://www.cnblogs.com/zhengyuhong/p/3645059.html
标签:style blog http color 使用 os
原文地址:http://www.cnblogs.com/zhengyuhong/p/3817259.html