动态规划——最长公共子序列问题(LCS)的java实现

本文介绍了一种使用动态规划解决最长公共子序列(LCS)问题的方法,并通过具体实例演示了算法实现的过程。代码示例展示了如何构建LCS长度数组及如何通过反向追踪找出两个字符串之间的最长公共子序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现的是别人博客中的思路,博客地址为 动态规划 最长公共子序列 过程图解

这个人写的很好,虽然有少许几处表述对涉及场景描述不清,但如果有代码的话一看就应该明白。作者没提供实现,我便实现了下,运行ok的,回头找个oj系统跑下.

public class LCS2 {

    public static void main(String[] args) {
        String str1 = "13456778";
        String str2 = "357486782";
        printLCS(str1, str2);
    }

    public static void printLCS(String str1, String str2) {
        /**
         * //非算法相关代码,仅保证无异常
         if(null==str1){
         str1="";
         }
         if(null==str2){
         str2="";
         }
         */

        int str1Len = str1.length();
        int str2Len = str2.length();
        int[][] cLenNUm = new int[str1.length() + 1][str2.length() + 1];//默认赋值,[0][?],[?][0]默认两侧皆0,类似公式中0的场景
        //构造一个LCS长度数组
        for (int i = 1; i <= str1Len; i++) {
            for (int j = 1; j <= str2Len; j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {//对应公式第二条相等
                    cLenNUm[i][j] = cLenNUm[i - 1][j - 1] + 1;
                } else {//对应公式第三条不相等
                    cLenNUm[i][j] = Math.max(cLenNUm[i][j - 1], cLenNUm[i - 1][j]);
                }
            }
        }

        //反推结果
        int i = str1Len;
        int j = str2Len;
        StringBuffer sb = new StringBuffer();//作为结果
        while (i > 0 && j > 0) {//这里其实处理了i=0,j=0的,对应公式0的反推场景
            if (str1.charAt(i - 1) == str2.charAt(j - 1)) {//反推公式中不相等的场景
                //该值一定是被选取到的,根据之前的公式,知道两条字符串的下标都前进一位
                sb.append(str1.charAt(i - 1));
                i--;
                j--;
            } else {//对应公式中不相等的反推场景
                if (cLenNUm[i][j - 1] > cLenNUm[i - 1][j]) {//找大的那个方向,此处是左边大于上面,则该处的结果是来自左边
                    j--;
                } else if (cLenNUm[i][j - 1] < cLenNUm[i - 1][j]) {
                    i--;
                } else if (cLenNUm[i][j - 1] == cLenNUm[i - 1][j]) {
                    //对于有分支的可能时,我们选取单方向
                    i--;   //此结果对于结果1所选取方向,str1的下标左移一位.替换为j--,则结果对应与结果2选取的方向
                }
            }
        }
        //由于是从后往前加入字符的,需要反转才能得到正确结果
        System.out.println(sb.reverse().toString());
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值