【LeetCode】72.(最短)编辑距离(闫氏dp,分析加可视化)

【LeetCode】72.(最短)编辑距离(闫氏dp,分析加可视化)_第1张图片

 考虑两个数组:a、b

定义dp[ i ][ j ]为,让数组a从1到 i 的字符,与数组b从1到 j 的字符,正好匹配上的最小操作数。

假设现在面前有一个正好匹配的数组a和b,其中a的长度为 i ,b的长度为 j (两个数组下标都从1开始),那么达到正好匹配状态的上一步,有可能是增、删、改。

(1)如果上一步是增,则数组a的尾巴加上1个字符就正好匹配数组b,也就是说,原本数组a的1到 i 个字符应恰好匹配数组b的1到 j-1个字符(达到这一条件的操作数是dp[ i ][ j-1]),在此基础上加一步增的操作即可。公式表示为:

dp[ i ][ j ] = dp[ i ][ j-1] + 1

(2)如果上一步是删,则数组a的尾巴减去一个字符就正好匹配数组b,也就是说,原本数组a的1到 i-1 个字符应恰好匹配数组b的1到 j 个字符(达到这一条件的操作数是dp[ i-1][ j ]),在此基础上加一步删的操作即可,则有:

dp[ i ][ j ] = dp[ i-1][ j ] + 1

(3)如果上一步是改,则数组a的第 i 个字符改成数组b的第 j 个字符就正好匹配数组b,也就是说,原本数组a的第1到 i -1个字符应恰好匹配数组b的第1到 j-1个字符(达到这一条件的操作数是dp[ i-1][ j-1]),在此基础上加一步删的操作即可,则有:

dp[ i ][ j ] = dp[ i-1][ j-1] + 1

(4)以上三种情况都是考虑的需要修改的情况,如果数组a的第 i 个字符恰好等于数组b的第 j 个字符,那么就直接取,让数组a的1到i-1个字符恰好匹配数组b的第1到j-1个字符的操作数(dp[i-1][j-1])即可,也就是:

dp[ i ][ j ] = dp[ i-1][ j-1]

class Solution {
public:
    int minDistance(string word1, string word2) {
        word1 = ' '+word1;
        word2 = ' '+word2;
        int len1 = word1.length();
        int len2 = word2.length();
        int dp[510][510] = {0};
//dp数组用vector容器存放可以提高速度
//vector> dp(n + 1, vector(m + 1));
        for (int i = 1;i <= len1;++i) dp[i][0] = i;
        for (int i = 1;i <= len2;++i) dp[0][i] = i;
        for (int i = 1;i <= len1;++i)
            for (int j = 1;j <= len2; ++j)
            {
                if(word1[i] == word2[j]) dp[i][j] = dp[i-1][j-1];
//如果两个数组的最后一个字符相等,则不需要额外的操作
//直接取让数组a的1到i-1个字符恰好匹配数组b的第1到j-1个字符的操作数(dp[i-1][j-1])即可
                else
            dp[i][j] = min(min(dp[i-1][j] + 1,dp[i][j-1] + 1),dp[i-1][j-1] + 1);
//最后一个字母不相等则要三种操作数里面取最小值
            }
        return dp[len1][len2];
    }
};

推荐一个可视化视频:

编辑距离 - 动态规划解法 Edit Distance - Dynamic Programming_哔哩哔哩_bilibili

你可能感兴趣的:(数据结构与算法,题解,leetcode,算法,职场和发展)