leetcode72.编辑距离

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
示例 1:

输入: word1 = "horse", word2 = "ros"
输出: 3
解释: 
horse -> rorse ('h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入: word1 = "intention", word2 = "execution"
输出: 5
解释: 
intention -> inention (删除 't')
inention -> enention ('i' 替换为 'e')
enention -> exention ('n' 替换为 'x')
exention -> exection ('n' 替换为 'c')
exection -> execution (插入 'u')

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/edit-distance
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

完整代码

编辑距离算法
计算过程

  • 定义比原有字符串长度大1的二维矩阵
  • 初始化:矩阵第0行对应0,1,2,……递增,第0列也是一样
  • 矩阵其他位置的元素是多少?
    如果相应位置的两个字符相等,该位置的值等于矩阵左上方、上方+1、左侧+1的最小值;两字符不想等,该位置的值等于左上方+1、上方+1、左侧+1的最小值

算法思想
动态规划:将字符串s转化成字符串t,借助动态规划的思想,定义一个数组cell,数组是二维数组一共有s.length()+1行,t.length()+1列。这里增加一行是因为在子问题中会出现当s为空时转化成t代价

  • 转化的过程:增加、删除、替换
  • 初始时,对于数组的第0行,相当于将一个空字符转化成t[0…j]的代价,该代价相当于增加j+1个字符;对于数组的第0列,相当于将字符s[0…i]转化成空字符的代价,该代价相当于删除i+1个字符.
  • 在求解的过程中要考虑三种情况,从s[0…i]到t[0…j]如何变化代价最小,其依赖于上一步的变化情况,从上一步到这一步有三种可能,还要分两种情况进行考虑
  • 先说第一种情况,当前i,j所指的字符都相等,那要考虑该步做替换(cell[i-1][j-1])的代价,这里不用+1,因为两个字符是相等的呀,还是该步进行删除(cell[i-1][j]+1),还是该步进行增加(cell[i][j-1]+1)这三种情况哪一个代价最小.两个字符相等可以稍微简化一点,cell[i][j]=cell[i-1][j-1],经测试结果正确
  • 第二种情况是指当前两个字符不想等的情况,和上面稍微有一点区别,替换的代价要在上一步基础上进行+1,依然是考虑这三种情况,哪一种代价最小。
    cell[i-1][j-1]到cell[i][j]进行替换操作;cell[i-1][j]到cell[i][j]进行删除操作;cell[i][j-1]到cell[i][j]进行增加操作
class Solution {
public:
    int minDistance(string word1, string word2) {
        //直接借助编辑距离算法
        vector<vector<int>> cell(word1.length()+1);
        //1.初始化
        //初始化第0行
        for(int i = 0; i <= word2.length(); ++i){
            cell[0].push_back(i);
        }
        //初始化第0列
        for(int j = 1; j <= word1.length(); ++j){
            cell[j].push_back(j);
        }
        //2.求编辑距离
        for(int i = 1; i <= word1.length(); ++i){
            for(int j = 1; j <= word2.length(); ++j){
                if(word1[i-1] == word2[j-1]){
                    //两字符相等,存入的是左上方以及左边+1、右边+1的最小值
                    cell[i].push_back(three_min(cell[i-1][j-1], cell[i-1][j] + 1, cell[i][j - 1] + 1));
                }
                else{
                    //不相等时,存入的是左上方、左边、上边的最小值+1
                    cell[i].push_back(three_min(cell[i-1][j-1], cell[i-1][j], cell[i][j - 1]) + 1);
                }
            }
        }
        return cell[word1.length()][word2.length()];
    }
private:
    int three_min(int a, int b, int c){
        int min;
        min = (a < b)? a : b;
        min = (min < c)? min : c;
        return min;
    }
};

说明:不管是将word1变成word2,还是将word2编程word1步数都是一样的。

发布了217 篇原创文章 · 获赞 9 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_31672701/article/details/103964740