题目地址:
https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/description/
给定两个字符串 s 1 , s 2 s_1,s_2 s1,s2,可以删除任一字符串的任意多个字符,总代价为删除的字符的ASCII码总和。求让它们变得相等的最小总代价。
设 f [ i ] [ j ] f[i][j] f[i][j]是 s 1 s_1 s1前 i i i个字符的前缀和 s 2 s_2 s2前 j j j个字符的前缀要变得相等,操作的最小总代价。那么 f [ 0 ] [ 0 ] = 0 f[0][0]=0 f[0][0]=0。接下来下标从 1 1 1开始,可以按照 s 1 [ i ] s_1[i] s1[i]和 s 2 [ j ] s_2[j] s2[j]是否做删除来分类,如果删 s 1 [ i ] s_1[i] s1[i],则最小总代价为 f [ i − 1 ] [ j ] + s 1 [ i ] f[i-1][j]+s_1[i] f[i−1][j]+s1[i];如果删 s 2 [ j ] s_2[j] s2[j],结论类似;如果都删,则最小总代价为 f [ i − 1 ] [ j − 1 ] + s 1 [ i ] + s 2 [ j ] f[i-1][j-1]+s_1[i]+s_2[j] f[i−1][j−1]+s1[i]+s2[j];如果 s 1 [ i ] = s 2 [ j ] s_1[i]=s_2[j] s1[i]=s2[j],那么不删也是一种选择,最小总代价为 f [ i − 1 ] [ j − 1 ] f[i-1][j-1] f[i−1][j−1]。四个情况取最小即可。代码如下:
class Solution {
public:
int minimumDeleteSum(string s1, string s2) {
int m = s1.size(), n = s2.size();
s1 = " " + s1, s2 = " " + s2;
int f[m + 1][n + 1];
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for (int i = 0; i <= m; i++)
for (int j = 0; j <= n; j++) {
if (!i && !j) continue;
if (!i) f[i][j] = f[i][j - 1] + s2[j];
else if (!j) f[i][j] = f[i - 1][j] + s1[i];
else {
f[i][j] = min(f[i - 1][j] + s1[i], f[i][j - 1] + s2[j]);
if (s1[i] == s2[j]) f[i][j] = min(f[i][j], f[i - 1][j - 1]);
else f[i][j] = min(f[i][j], f[i - 1][j - 1] + s1[i] + s2[j]);
}
}
return f[m][n];
}
};
时空复杂度 O ( l s 1 l s 2 ) O(l_{s_1}l_{s_2}) O(ls1ls2)。