3.3计算字符串的相似度

计算字符串的相似度

题目:

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

1.      修改一个字符(如把“a”替换为“b”)

2.      增加一个字符(如把“abdd”变为“aebdd”)

3.      删除一个字符(如把“travelling”变为“traveling”)

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

的距离为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[1,…,lenA]和B[2,…,lenB]变成相同的字符串

3.        一步操作后,再将A[2,…,lenA]和B[2,…,lenB]变成相同的字符串

这样,很快就可以完成一个递归程序

代码清单:

//略,下给出优化的代码

上述程序有些数据被重复计算了,可以使用数组存储子问题的解。

//使用数组的代码
int checkPoint[20][20] = {0};//使用数组来存储子问题是否已经计算
int minValue(int t1,int t2,int t3){
    int temp = t1 < t2 ? t1 : t2;
    return temp < t3 ? temp : t3;
}
int CalculateStringDistance(string strA,int pABegin,int pAEnd,string strB,int pBBegin,int pBEnd){
    if(pABegin > pAEnd){//A串到末尾了,两串比较完成了
        if(pBBegin > pBEnd)//B串也到末尾了,则说明两串距离为0
            return 0;
        else
            return pBEnd - pBBegin + 1;
    }
    if(pBBegin > pBEnd){
        if(pABegin > pAEnd)
            return 0;
        else
            return pAEnd - pABegin + 1;
    }
    if(strA[pABegin] == strB[pBBegin]){
        return CalculateStringDistance(strA,pABegin + 1,pAEnd,strB,pBBegin + 1,pBEnd);
    }else{
        int t1 = 0,t2 = 0, t3 = 0;

        if(checkPoint[pABegin + 1][pBBegin] == 0){
            checkPoint[pABegin + 1][pBBegin] = t1 = CalculateStringDistance(strA,pABegin + 1,pAEnd,strB,pBBegin,pBEnd);
        }else{
            t1 = checkPoint[pABegin + 1][pBBegin];
        }

        if(checkPoint[pABegin][pBBegin + 1] == 0){
            checkPoint[pABegin][pBBegin + 1] = t2 = CalculateStringDistance(strA,pABegin,pAEnd,strB,pBBegin + 1,pBEnd);
        }else{
            t2 = checkPoint[pABegin][pBBegin + 1];
        }

        if(checkPoint[pABegin + 1][pBBegin + 1] == 0){
            checkPoint[pABegin + 1][pBBegin + 1] = t3 = CalculateStringDistance(strA,pABegin + 1,pAEnd,strB,pBBegin + 1,pBEnd);
        }else{
            t3 = checkPoint[pABegin + 1][pBBegin + 1];
        }

        return minValue(t1,t2,t3) + 1;
    }
}


你可能感兴趣的:(算法,String,编程之美)