--- comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0700-0799/0712.Minimum%20ASCII%20Delete%20Sum%20for%20Two%20Strings/README.md tags: - 字符串 - 动态规划 --- # [712. 两个字符串的最小ASCII删除和](https://leetcode.cn/problems/minimum-ascii-delete-sum-for-two-strings) [English Version](/solution/0700-0799/0712.Minimum%20ASCII%20Delete%20Sum%20for%20Two%20Strings/README_EN.md) ## 题目描述

给定两个字符串s1 和 s2,返回 使两个字符串相等所需删除字符的 ASCII 值的最小和 

 

示例 1:

输入: s1 = "sea", s2 = "eat"
输出: 231
解释: 在 "sea" 中删除 "s" 并将 "s" 的值(115)加入总和。
在 "eat" 中删除 "t" 并将 116 加入总和。
结束时,两个字符串相等,115 + 116 = 231 就是符合条件的最小和。

示例 2:

输入: s1 = "delete", s2 = "leet"
输出: 403
解释: 在 "delete" 中删除 "dee" 字符串变成 "let",
将 100[d]+101[e]+101[e] 加入总和。在 "leet" 中删除 "e" 将 101[e] 加入总和。
结束时,两个字符串都等于 "let",结果即为 100+101+101+101 = 403 。
如果改为将两个字符串转换为 "lee" 或 "eet",我们会得到 433 或 417 的结果,比答案更大。

 

提示:

## 解法 ### 方法一:动态规划 我们定义 $f[i][j]$ 表示使得 $s_1$ 的前 $i$ 个字符和 $s_2$ 的前 $j$ 个字符相等所需删除字符的 ASCII 值的最小和。那么答案就是 $f[m][n]$。 如果 $s_1[i-1] = s_2[j-1]$,那么 $f[i][j] = f[i-1][j-1]$。否则,我们可以删除 $s_1[i-1]$ 或者 $s_2[j-1]$ 中的一个,使得 $f[i][j]$ 达到最小。因此,状态转移方程如下: $$ f[i][j]= \begin{cases} f[i-1][j-1], & s_1[i-1] = s_2[j-1] \\ min(f[i-1][j] + s_1[i-1], f[i][j-1] + s_2[j-1]), & s_1[i-1] \neq s_2[j-1] \end{cases} $$ 初始状态为 $f[0][j] = f[0][j-1] + s_2[j-1]$, $f[i][0] = f[i-1][0] + s_1[i-1]$。 最后返回 $f[m][n]$ 即可。 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是 $s_1$ 和 $s_2$ 的长度。 相似题目: - [1143. 最长公共子序列](https://github.com/doocs/leetcode/blob/main/solution/1100-1199/1143.Longest%20Common%20Subsequence/README.md) #### Python3 ```python class Solution: def minimumDeleteSum(self, s1: str, s2: str) -> int: m, n = len(s1), len(s2) f = [[0] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): f[i][0] = f[i - 1][0] + ord(s1[i - 1]) for j in range(1, n + 1): f[0][j] = f[0][j - 1] + ord(s2[j - 1]) for i in range(1, m + 1): for j in range(1, n + 1): if s1[i - 1] == s2[j - 1]: f[i][j] = f[i - 1][j - 1] else: f[i][j] = min( f[i - 1][j] + ord(s1[i - 1]), f[i][j - 1] + ord(s2[j - 1]) ) return f[m][n] ``` #### Java ```java class Solution { public int minimumDeleteSum(String s1, String s2) { int m = s1.length(), n = s2.length(); int[][] f = new int[m + 1][n + 1]; for (int i = 1; i <= m; ++i) { f[i][0] = f[i - 1][0] + s1.charAt(i - 1); } for (int j = 1; j <= n; ++j) { f[0][j] = f[0][j - 1] + s2.charAt(j - 1); } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (s1.charAt(i - 1) == s2.charAt(j - 1)) { f[i][j] = f[i - 1][j - 1]; } else { f[i][j] = Math.min(f[i - 1][j] + s1.charAt(i - 1), f[i][j - 1] + s2.charAt(j - 1)); } } } return f[m][n]; } } ``` #### C++ ```cpp class Solution { public: int minimumDeleteSum(string s1, string s2) { int m = s1.size(), n = s2.size(); int f[m + 1][n + 1]; memset(f, 0, sizeof f); for (int i = 1; i <= m; ++i) { f[i][0] = f[i - 1][0] + s1[i - 1]; } for (int j = 1; j <= n; ++j) { f[0][j] = f[0][j - 1] + s2[j - 1]; } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (s1[i - 1] == s2[j - 1]) { f[i][j] = f[i - 1][j - 1]; } else { f[i][j] = min(f[i - 1][j] + s1[i - 1], f[i][j - 1] + s2[j - 1]); } } } return f[m][n]; } }; ``` #### Go ```go func minimumDeleteSum(s1 string, s2 string) int { m, n := len(s1), len(s2) f := make([][]int, m+1) for i := range f { f[i] = make([]int, n+1) } for i, c := range s1 { f[i+1][0] = f[i][0] + int(c) } for j, c := range s2 { f[0][j+1] = f[0][j] + int(c) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if s1[i-1] == s2[j-1] { f[i][j] = f[i-1][j-1] } else { f[i][j] = min(f[i-1][j]+int(s1[i-1]), f[i][j-1]+int(s2[j-1])) } } } return f[m][n] } ``` #### TypeScript ```ts function minimumDeleteSum(s1: string, s2: string): number { const m = s1.length; const n = s2.length; const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { f[i][0] = f[i - 1][0] + s1[i - 1].charCodeAt(0); } for (let j = 1; j <= n; ++j) { f[0][j] = f[0][j - 1] + s2[j - 1].charCodeAt(0); } for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { if (s1[i - 1] === s2[j - 1]) { f[i][j] = f[i - 1][j - 1]; } else { f[i][j] = Math.min( f[i - 1][j] + s1[i - 1].charCodeAt(0), f[i][j - 1] + s2[j - 1].charCodeAt(0), ); } } } return f[m][n]; } ``` #### JavaScript ```js /** * @param {string} s1 * @param {string} s2 * @return {number} */ var minimumDeleteSum = function (s1, s2) { const m = s1.length; const n = s2.length; const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { f[i][0] = f[i - 1][0] + s1[i - 1].charCodeAt(0); } for (let j = 1; j <= n; ++j) { f[0][j] = f[0][j - 1] + s2[j - 1].charCodeAt(0); } for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { if (s1[i - 1] === s2[j - 1]) { f[i][j] = f[i - 1][j - 1]; } else { f[i][j] = Math.min( f[i - 1][j] + s1[i - 1].charCodeAt(0), f[i][j - 1] + s2[j - 1].charCodeAt(0), ); } } } return f[m][n]; }; ```