编辑距离(一)&(二)

98 阅读4分钟

1. 原题链接

编辑距离(一)

编辑距离(二)

2. 编辑距离(一)题解

题目描述

image.png

方法模板

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param str1 string字符串
 * @param str2 string字符串
 * @return int整型
 */
public int editDistance(String str1, String str2) {
    // write code here

}

题目分析

  1. 首先分析题目,看描述,应该是得用动态规划
  2. 动态规划第一步,定义dp数值的含义:二位数组,标识将字符串a从i长度变成字符串b的j长度的最少操作数
  3. 动态规划第二步,定义公式
  • 当a[i] == b[j] 的时候,dp[i][j] = dp[i-1][j-1]
  • 当a[i] != b[j] 的时候,我们需要进行插入、删除、替换操作分别是:
    • 插入:dp[i][j] = dp[i][j-1] + 1:

例如下面两个字符串,abc 变成 abcd,在abc 和 abc对齐的基础上,需要插入一个d

abc

abcd

    • 替换:dp[i][j] = dp[i-1][j-1] + 1

例如下面两个字符串,abc 变成 abcd,在abc 和 abc对齐的基础上,需要把t替换成d

abct

abcd

    • 删除:dp[i][j] = dp[i-1][j] + 1

例如下面两个字符串,abc 变成 abcd,在abc 和 abc对齐的基础上,需要把t删除

abct

abc

    • 最后我们在什么三个操作里面选取一个最小值
  1. 动态规划第三步,确定递推公式
dp[i][j] = dp[i-1][j-1]; //a[i] == b[j]
dp[i][j] = min(dp[i-1][j],dp[i-1][j-1],dp[i][j-1]) + 1; //a[i] != b[j]
  1. 动态规划第5步,确定边界条件
  • 当字符串a的长度为0时,dp[0][j] = j;
  • 当字符串b的长度为0时,dp[i][0] = i;

最终代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param str1 string字符串
     * @param str2 string字符串
     * @return int整型
     */
    public int editDistance(String str1, String str2) {
        // write code here
        int n = str1.length();
        int m = str2.length();
        int[][] dp = new int[n + 1][m + 1];
        for (int i = 1; i <= n; i++) {
            dp[i][0] = i;
        }

        for (int i = 1; i <= m; i++) {
            dp[0][i] = i;
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i-1][j-1];
                } else {
                    dp[i][j] = Math.min(dp[i-1][j], Math.min(dp[i-1][j-1], dp[i][j -1])) + 1;
                }
            }
        }
        return dp[n][m];
    }
}

3. 编辑距离(二)题解

题目描述

image.png

image.png

方法模板

public int minEditCost (String str1, String str2, int ic, int dc, int rc) {
    // write code here

}

题目分析

相对于编辑距离(一),只是插入、替换、删除的操作的代价从都是1 变成了可定义,那么我们的分析如下:

  1. 首先分析题目,看描述,还是是得用动态规划
  2. 动态规划第一步,定义dp数值的含义:二位数组,标识将字符串a从i长度变成字符串b的j长度的最少操作代价
  3. 动态规划第二步,定义公式
  • 当a[i] == b[j] 的时候,dp[i][j] = dp[i-1][j-1]
  • 当a[i] != b[j] 的时候,我们需要进行插入、删除、替换操作分别是:
    • 插入:dp[i][j] = dp[i][j-1] + ic:

例如下面两个字符串,abc 变成 abcd,在abc 和 abc对齐的基础上,需要插入一个d

abc

abcd

    • 替换:dp[i][j] = dp[i-1][j-1] + rc

例如下面两个字符串,abc 变成 abcd,在abc 和 abc对齐的基础上,需要把t替换成d

abct

abcd

    • 删除:dp[i][j] = dp[i-1][j] + dc

例如下面两个字符串,abc 变成 abcd,在abc 和 abc对齐的基础上,需要把t删除

abct

abc

    • 最后我们在什么三个操作里面选取一个最小值
  1. 动态规划第三步,确定递推公式
dp[i][j] = dp[i-1][j-1]; //a[i] == b[j]
dp[i][j] = min(dp[i-1][j] + dc, dp[i-1][j-1] + rc, dp[i][j-1] + ic); //a[i] != b[j]
  1. 动态规划第5步,确定边界条件
  • 当字符串a的长度为0时,dp[0][j] = j * ic;
  • 当字符串b的长度为0时,dp[i][0] = i * dc;

主要变化的是递推公式a[i]!=b[j]时的取值和边界的取值

最终代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * min edit cost
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @param ic int整型 insert cost
     * @param dc int整型 delete cost
     * @param rc int整型 replace cost
     * @return int整型
     */
    public int minEditCost (String str1, String str2, int ic, int dc, int rc) {
        // write code here
        int n = str1.length();
        int m = str2.length();
        int[][] dp = new int[n + 1][m + 1];
        for (int i = 1; i <= n; i++) {
            dp[i][0] = i * dc;
        }

        for (int i = 1; i <= m; i++) {
            dp[0][i] = i * ic;
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i-1][j-1];
                } else {
                    dp[i][j] = Math.min(dp[i-1][j] + dc, Math.min(dp[i-1][j-1] + rc, dp[i][j -1] + ic));
                }
            }
        }
        return dp[n][m];
    }
}

4. 参考文献

代码随想录programmercarl.com/%E5%8A%A8%E…