DP:最长公共子序列Ⅰ

DP:最长公共子序列Ⅰ

问题

在这里插入图片描述
在这里插入图片描述

思路

  我们先从最简单的情况入手,设两个字符串为A,B,如果只看两个串的前1个字符,那么如果A[1]等于B[1],最长公共子序列为1;如果A[1]不等于B[1],最长公共子序列为0。如果只看前2个字符,如果A[2]等于B[2],最长公共子序列长度是否等于之前只看前1个字符时的答案+1呢?一个公共子序列一定包含在从第一个字符开始的某个连续序列中,而不同连续序列以不同位置的字符结尾,如果用DP[i]表示两个串前i个字符以第i个字符结尾的最长公共子序列的长度,那么有DP[i]=max{DP[j],j=1~i-1}+(A[i]==B[i])吗?实际上我们不能用这个状态转移方程解题,使用该方程的前提是:两个字符串中连续序列以同一位置i的字符结尾,也就是所判断的两个连续序列是位置对应长度相同的,但题目中并没有要求这一点,公共子序列可以出现在两个字符串的不同连续序列中,再来看看最开始的例子,我们并没有考虑到A[2] = B[1] 或 B[2] = A[1]的情况,也就是说,使用一维dp数组表达不出所有的状态。
  为了表示公共子序列处于两个字符串长度不同的连续序列中,我们需要用二维dp数组来表示所有的状态。我们用DP[ i ] [ j ]表示A[1 ~ i] 与 B[1 ~ j]的最长公共子序列的长度,若A[i]==B[j],则DP[i] [j]由DP[i - 1] [j - 1] + 1转移得到,若不等,则DP[i - 1] [j - 1]由Max(DP[i - 1][j],DP[i][j - 1])转移得到,注意不等的情况并不是继承DP[i - 1] [j - 1],因为A[i]虽不等于B[j],但A[i]可能与B[1 ~ j - 1]包含的子序列中最后一个元素相等,同理,B[j]可能与A[1 ~ i - 1]包含的子序列中最后一个元素相等。
  所以状态转移方程为:
在这里插入图片描述
  初始状态DP[0][0]表示两个空串的最长公共子序列,即为0。

代码

import java.util.*;

public class Main {
    static int[][] dp = new int[1005][1005];
    public static void main(String[] args) {
        StringBuilder str1 = new StringBuilder();
        StringBuilder str2 = new StringBuilder();
        int i, j, ans;
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            ans = 0;
            str1.delete(0, str1.length());
            str1.append(scanner.next());
            str2.delete(0, str2.length());
            str2.append(scanner.next());
            dp[0][0] = 0;
            for (i = 1;i <= str1.length();i++) {
                for (j = 1;j <= str2.length();j++) {
                    if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                    } else {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                    }
                    ans = Math.max(ans, dp[i][j]);
                }
            }
            System.out.println(ans);
        }
    }
}

  代码中除初始化dp[0][0] = 0外,无需做其他重置或初始化工作,因为双循环变量都是从1开始,dp[0][]和dp[][0]一直等于0,不会被赋值,dp数组填充也是从前向后遍历,当前测试样例不会受前一个测试样例造成的脏数据影响

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

happy19991001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值