NC92 最长公共子序列(二)

题目
知识点
动态规划
描述
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列

示例1
输入:
“1A2C3D4B56”,“B1D23A456A”
返回值:
“123456”

示例2
输入:
“abc”,“def”
返回值:
“-1”

示例3
输入:
“abc”,“abc”
复制
返回值:
“abc”

示例4
输入:
“ab”,""
复制
返回值:
“-1”

细节讲解的博客地址:https://blog.csdn.net/hrn1216/article/details/51534607

思路:new一个二维的dp数组,存放两个字符串相同个数的。
1、我们发现,当两个字符串一样时,数组的对角线位置是依次加1的。说明当字符相同时,数据来源于左上角的位置+1。
2、若字符不相同,数据来源于左边或上边,取最大值。
3、寻找子序列,从后往前推,如果字符相同,那都减1。如果不同,从数组中往大的位置走,因为不同时,数据就来自较大的位置。

package mid;

public class LCS {

    public static void main(String[] args) {
        String lcs = lcs("13456778", "357486782");
        System.out.println(lcs);
    }
    public static String lcs (String s1, String s2) {
        // write code here
        int len1=s1.length();
        int len2=s2.length();
        if (len1==0 || len2==0){
            return "-1";
        }
        int[][] dp = new int[len1+1][len2+1];
        //第一行,一列 填0(默认赋值)
        for (int i = 1; i < len1 + 1; i++) {
            for (int j = 1; j < len2 + 1; j++) {
                if (s1.charAt(i-1)==s2.charAt(j-1)){
                    //假设字符串全部相同,那么矩阵的对角线上的点会依次加1,如果有相同字符时,数据来源是 左上角的数+1
                    dp[i][j] = dp[i-1][j-1]+1;
                }else {
                    //若不相同,那么数据来源可能是左边,也可能是上边,谁多取谁
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        //找出一个符合的子序列
        int length1 = len1;
        int length2 = len2;
        StringBuilder ans = new StringBuilder();
        //从后往前推
        while (length1>0 && length2>0){
            //如果字符相同就都减一
            if (s1.charAt(length1-1)==s2.charAt(length2-1)){
                ans.append(s1.charAt(length1-1));
                length1--;
                length2--;
            }else {
                //如果不同,那找大的那个方向,如果左边大于上面,那最右一列就无用了,所以length2--
                if (dp[length1][length2-1]>dp[length1-1][length2]){
                    length2--;
                }else {//如果左边小于等于上面,最下面一行就没用了
                    length1--;
                }
            }
        }
        if (ans.length()==0){
            return "-1";
        }
        return ans.reverse().toString();
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值