您的位置:首页 > 其它

【刷题之路】字符串的编辑距离

2016-06-07 11:24 197 查看
对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法,求出将A串变为B串所需要的最少代价。

给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。保证两串长度均小于等于300,且三种代价值均小于等于100。

经典动态规划问题,简历一个二维数组来解决问题

首先确定初始状态,先建立一个m+1*n+1的二维数组,其中行数是B,列数是A,数组的左上角为A,B都为空字符串时,显然操作数为0,对于第一行,显然是当B为空时,不断扩大A时所需要的操作,显然需要不断删除A中元素来达到,所以第一行里的操作数为i*c1,同理对于第一列,A为空不断扩大B,则需要不断将B中字符插入A中,所以第一列的操作数为i*c0。初始状态设置完毕

对于数组中某一个res[i][j]来说,可能的状态一共有四种,

1、对于当前A来说,删除一个字符,然后将删除后的字符字符串再去变为当前B,而删去一个字符之后,变为B的最小操作数为res[i][j-1],即res[i][j]=res[i][j-1]+c1;

2、对于当前A来说,插入一个字符,然后将插入后的字符串再去变为当前B,插入一个字符后最小操作数,为res[i-1][j](注:这里需要理解,前两种操作的本质实际上是字符串对齐,也就是说让这之前的字符串全部相等,然后再去考虑后面的,例如这个插入操作,并不是res[i][j+1],因为我是要将A变为B,所以当插入一个字符后,应该将当前的A与上一个B的最小操作数返回,因为假如需要插入的话,必然是A短,加入了一个字符后应该基于没加入字符时的状态的B比较,也就是res[i-1][j])即res[i][j]=res[i-1][j]+c0;

3、对于当前A来说,替换一个字符,然后将替换后的字符串再去变为B,即res[i][j]=res[i-1][j-1]+c2,

4、对与当前A来说,如果与当前B字符相同,可以考虑不变化,即res[i][j]=res[i-1][j-1](3与4实际上是二选一,因为我们需要的是最小的操作数)

取四种操作数中最小的作为当前位置的值,代码如下

class MinCost {

public:

    int findMinCost(string A, int n, string B, int m, int c0, int c1, int c2) {

        // write code here

        vector<int> sub(n+1);

        vector<vector<int>> res(m+1,sub);

        int i,j,temp1,temp2,temp3;

        for(i=0;i<=n;i++){

            res[0][i]=i*c1;

        }

        for(i=0;i<=m;i++){

            res[i][0]=i*c0;

        }

        for(i=1;i<=m;i++){

            for(j=1;j<=n;j++){

                temp1=res[i][j-1]+c1;

                temp2=res[i-1][j]+c0;

                if(A[j-1]==B[i-1]) temp3=res[i-1][j-1];

                else temp3=res[i-1][j-1]+min(c2,c0+c1);

                res[i][j]=min(temp1,min(temp2,temp3));  

            }

        }

        return res[m]
;

    }

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息