0
点赞
收藏
分享

微信扫一扫

STM32 uc/OS-III多任务程序

爪哇驿站 2024-06-09 阅读 28

一、题目描述

二、解题思路(动态规划)

正难则反:求两个字符串的最小 ASCII 删除和, 其实就是找到两个字符串中所有的公共子序列里面, ASCII 最大和。

因此,我们的思路就是按照最长公共子序列的分析方式来分析。

关于最长公共子序列问题,可以参考下面博客:

【力扣】最长公共子序列-CSDN博客 

1、状态表示

dp[i][j] 表示: s1 [0, i] 区间以及 s2 [0, j] 区间内的所有的子序列中,公 共子序列的 ASCII 最大和

2、状态转移方程

对于 dp[i][j] 根据最后一个位置的元素,结合题目要求,分情况讨论:

(1)当 s1[i] == s2[j] 时应该先在 s1 的 [0, i - 1] 区间以及 s2 的 [0, j - 1] 区间内找一个公共子序列的 ASCII 最大和,然后在它们后面加上一个 s1[i] 字符即可。

此时 dp[i][j] = dp[i - 1][j - 1] + s1[i];

(2)当 s1[i] != s2[j] 时:公共子序列的ASCII最大和会有三种可能:

  • s1 [0, i - 1] 区间以及 s2 [0, j] 区间内:此时 dp[i][j] = dp[i - 1][j] ;
  • s1 [0, i] 区间以及 s2 [0, j - 1] 区间内:此时 dp[i][j] = dp[i][j - 1] ;
  • s1 [0, i - 1] 区间以及 s2 [0, j - 1] 区间内:此时 dp[i][j] = dp[i - 1][j - 1]

但是前两种情况里面包含了第三种情况,因此仅需考虑前两种情况下的最大值即可。

综上所述,状态转移方程为:

当 s1[i - 1] == s2[j - 1] 时, dp[i][j] = dp[i - 1][j - 1] + s1[i] ;

当 s1[i - 1] != s2[j - 1] 时, dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

3、初始化

我们将原始 dp 表的规模多加上一行和一列,表示空串。 引入空串后,大大的方便了初始化。

但要 注意下标的映射关系 ,以及里面的值要保证后续填表是正确的。

当 s1 为空时,没有长度,同理 s2 也是。因此第一行和第一列里面的值初始化为 0,即可保证

后续填表是正确的。

4、填表顺序

从上往下填每一行,每一行从左往右。

5、返回值

(1)先找到 dp[m][n] ,也是最大公共 ASCII 和;(2)统计两个字符串的 ASCII 码和 sum; (3)返回 sum - 2 * dp[m][n]

三、代码

public int minimumDeleteSum(String s1, String s2) {
        int m = s1.length();
        int n = s2.length();
        int[][] dp = new int[m+1][n+1];
        for(int i = 1; i <= m; i++) {
            for(int j = 1; j <= n; j++) {
                if(s1.charAt(i-1) == s2.charAt(j-1)) {
                    dp[i][j] = dp[i-1][j-1] + s1.charAt(i-1);
                }else {
                    dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
                }
            }
        }
        int sum = 0;
        for(char ch : s1.toCharArray()) {
            sum += ch;
        }
        for(char ch : s2.toCharArray()) {
            sum += ch;
        }
        return sum - dp[m][n] - dp[m][n];
    }
举报

相关推荐

0 条评论