Files
leetcode-master/problems/kamacoder/0142.两个字符串的最小ASCII删除总和.md
programmercarl 2d9604baa5 Update
2024-07-26 11:35:38 +08:00

3.6 KiB
Raw Blame History

142. 两个字符串的最小 ASCII 删除总和

本题和代码随想录:两个字符串的删除操作 思路基本是一样的。

属于编辑距离问题,如果想彻底了解,建议看看「代码随想录」的编辑距离总结篇。

本题dp数组含义

dp[i][j] 表示 以i-1为结尾的字符串word1和以j-1位结尾的字符串word2想要达到相等所需要删除元素的最小ASCII 删除总和。

如果 s1[i - 1] 与 s2[j - 1] 相同,则不用删:dp[i][j] = dp[i - 1][j - 1]

如果 s1[i - 1] 与 s2[j - 1] 不相同删word1 的 最小删除和: dp[i - 1][j] + s1[i - 1] 删word2的最小删除和 dp[i][j - 1] + s2[j - 1]

取最小值: dp[i][j] = min(dp[i - 1][j] + s1[i - 1], dp[i][j - 1] + s2[j - 1])

#include <iostream>
#include <vector>
using namespace std;
int main() {
    string s1, s2;
    cin >> s1 >> s2;
    vector<vector<int>> dp(s1.size() + 1, vector<int>(s2.size() + 1, 0));

    // s1 如果变成空串的最小删除ASCLL值综合
    for (int i = 1; i <= s1.size(); i++) dp[i][0] = dp[i - 1][0] + s1[i - 1];
    // s2 如果变成空串的最小删除ASCLL值综合
    for (int j = 1; j <= s2.size(); j++) dp[0][j] = dp[0][j - 1] + s2[j - 1];

    for (int i = 1; i <= s1.size(); i++) {
        for (int j = 1; j <= s2.size(); j++) {
            if (s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
            else dp[i][j] = min(dp[i - 1][j] + s1[i - 1], dp[i][j - 1] + s2[j - 1]);
        }
    }
    cout << dp[s1.size()][s2.size()] << endl;
}

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s1 = scanner.nextLine();
        String s2 = scanner.nextLine();
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];

        // s1 如果变成空串的最小删除ASCII值综合
        for (int i = 1; i <= s1.length(); i++) {
            dp[i][0] = dp[i - 1][0] + s1.charAt(i - 1);
        }
        // s2 如果变成空串的最小删除ASCII值综合
        for (int j = 1; j <= s2.length(); j++) {
            dp[0][j] = dp[0][j - 1] + s2.charAt(j - 1);
        }

        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(dp[i - 1][j] + s1.charAt(i - 1), dp[i][j - 1] + s2.charAt(j - 1));
                }
            }
        }
        System.out.println(dp[s1.length()][s2.length()]);
        scanner.close();
    }
}


python

def min_delete_sum(s1: str, s2: str) -> int:
    dp = [[0] * (len(s2) + 1) for _ in range(len(s1) + 1)]

    # s1 如果变成空串的最小删除ASCII值综合
    for i in range(1, len(s1) + 1):
        dp[i][0] = dp[i - 1][0] + ord(s1[i - 1])
    # s2 如果变成空串的最小删除ASCII值综合
    for j in range(1, len(s2) + 1):
        dp[0][j] = dp[0][j - 1] + ord(s2[j - 1])

    for i in range(1, len(s1) + 1):
        for j in range(1, len(s2) + 1):
            if s1[i - 1] == s2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j] + ord(s1[i - 1]), dp[i][j - 1] + ord(s2[j - 1]))

    return dp[len(s1)][len(s2)]

if __name__ == "__main__":
    s1 = input().strip()
    s2 = input().strip()
    print(min_delete_sum(s1, s2))