算法训练营第五十六天|583. 两个字符串的删除操作、72. 编辑距离

60 阅读2分钟

583. 两个字符串的删除操作

本题和1143. 最长公共子序列基本相同,只要求出两个字符串的最长公共子序列长度即可,那么除了最长公共子序列之外的字符都是必须删除的,最后用两个字符串的总长度减去两个最长公共子序列的长度就是删除的最少步数。

class Solution {
    public int minDistance(String word1, String word2) {
        int l1 = word1.length();
        int l2 = word2.length();
        // dp[i][j]: 以i-1结尾的word1子串和以j-1结尾的word2子串的最长公共子序列长度
        int[][] dp = new int[l1 + 1][l2 + 1];
        
        for(int i = 0; i < l1; i++)dp[i][0] = 0;
        for(int j = 0; j < l2; j++)dp[0][j] = 0;

        for(int i = 1; i <= l1; i++){
            for(int j = 1; j <= l2; j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1))dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }

        return l1 + l2 - 2 * dp[l1][l2]; // 和1143题唯一不同的地方
    }
}

72. 编辑距离

class Solution {
    public int minDistance(String word1, String word2) {
        int l1 = word1.length();
        int l2 = word2.length();
        // dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
        int[][] dp = new int[l1 + 1][l2 + 1];

        for(int i = 0; i <= l1; i++){
            dp[i][0] = i;
        }
        for(int j = 0; j <= l2; j++){
            dp[0][j] = j;
        }

        for(int i = 1; i <= l1; i++){
            for(int j = 1; j <= l2; j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1))dp[i][j] = dp[i - 1][j - 1];
                // word2添加一个元素,相当于word1删除一个元素,所以三种情况就是word1删一个、word2删一个、替换一个
                else dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
            }
        }

        return dp[l1][l2];
    }
}