【动态规划】求最长公共子序列

一、解题思路

看到这题,我们先得知道怎么求最长公共子序列。

对于串A:a1,a2…an;串B:b1,b2…bm;我们将求子串定为F(n,m);
我们先比较an和bm两个字符,会有两种情况

  1. 如果相等,我们就会继续比较除最后一个字符的两个串,此时的公共子序列则为an;
    an == bm ,F(n,m) = F(n-1,m-1)+an;

  2. 如果不相等,则去比较 an和b(m-1) 或者 a(n-1)和bm ,选出其中子串最长的一个作为结果;
    an != bm, F(n,m) = Max(F(n,m-1),F(n-1,m));

这样一直比较到某串为空时,则结束。

注意:子序列并不要求连续,因此对于A串“abccd801” 和
B串“oabcdv8100”,它们的最长公共子序列为“abcd81”。但如果是最长公共子字符串的话,则为“abc”。

二、代码

public class LongestCommonSub  {
    //最长公共子序列的公共子序列里的元素可以不相邻,但是公共子字符串必须是连接在一起的,比如A和B的公共子字符串是“abcd81”。
    public static final String A = "abccd801";
    public static final String B = "oabcdv8100";

    public static String findLongestCommonSub(String a, String b) {
        if (a == null || b == null) {
            return "";
        }
        if (a.length() == 0 || b.length() == 0) {
            return "";
        }
        if (a.length() == 1) {
            if (b.contains(a)) {
                return a;
            }
        }
        if (b.length() == 1) {
            if (a.contains(b)) {
                return b;
            }
        }
        return findString(a, b, "");
    }

    private static String findString(String a, String b, String sameString) {
        if (a.length() == 0 || b.length() == 0) {
            return String.valueOf(sameString);
        }
        String result;
        if (getEndChar(a) == getEndChar(b)) {
            sameString = getEndChar(a) + sameString;
            result = findString(getUnEndString(a), getUnEndString(b), sameString);
        } else {
            String resultA = findString(getUnEndString(a), b, sameString);
            String resultB = findString(a, getUnEndString(b), sameString);
            result = resultA.length() > resultB.length() ? resultA : resultB;
        }
        return result;
    }

    private static char getEndChar(String s) {
        return s.charAt(s.length() - 1);
    }

    private static String getUnEndString(String s) {
        return s.substring(0, s.length() - 1);
    }
   }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值