【问题标题】:longest common subsequence java (recursive)最长公共子序列java(递归)
【发布时间】:2016-11-22 19:45:08
【问题描述】:

我正在处理的问题在这里: http://practiceit.cs.washington.edu/problem/view/cs2/sections/recursivebacktracking/longestCommonSubsequence

基本上我们得到两个字符串,我们被要求找到最长的公共子序列。我在网上搜索了解决方案并将它们与我自己的解决方案进行了比较,但我在我的代码中找不到任何错误。我想知道为什么它仍然不起作用。

另外,我被要求使用递归方法来解决这个问题

这是我的代码:

public static String longestCommonSubsequence(String a, String b){
    if(a.isEmpty() || b.isEmpty()){
        return "";
    }
    if (a.substring(a.length() - 1).equals(b.substring(b.length() - 1))){
        return longestCommonSubsequence(a.substring(0, a.length() - 1), b.substring(0, b.length()
                       - 1)) + a.substring(a.length() - 1);
    } else {
        String first = longestCommonSubsequence(a, b.substring(b.length() - 1));
        String second = longestCommonSubsequence(a.substring(a.length() - 1), b);
        if(first.length() > second.length()){
            return first;
        }
        return second;
    }
}

这里是所有的测试用例:

调用值返回

“ABCDEFG”、“BGCEHAF”、“BCEF”

“她卖”,“贝壳”“卖”

“12345”、“54321 21 54321”“123”

《白老师》、《好吃的桃子》、《各色各样》

“马蒂”,“海伦”“”

"","乔"""

“苏西”、“”“”

“ACGGTGTCGTGCTA”、“CGTTCGGCTATCGTACGT”“CGGTTCGTGT”

使用我的代码,我得到了所有测试用例的 StackOverFlow。

【问题讨论】:

  • 它可能有效。使用基于 DP 的解决方案的优势在于运行时间。
  • 但我得到的结果只是一个空字符串。我尝试调试并注意到String first = longestCommonSubsequence(a, b.substring(1)) 行一直在运行并切断字符串 b 中的字母,直到它为空。然后返回一个空字符串。
  • 具体来说,a.substring(0, 1) == b.substring(0, 1) 将始终为 false。
  • 所以我将“==”更改为 .equals(),它适用于多个测试。但显然还是有问题,因为它不适用于所有测试。

标签: java longest-substring recursive-backtracking


【解决方案1】:

您的 LCS 计算不正确。在 LCS 中,您需要从字符串末尾进行比较。如果两个字符串的最后一个字符匹配,则意味着它将成为 LCS 的一部分。

public static String longestCommonSubsequence(String a, String b) {
        int alength = a.length() - 1;
        int blength = b.length() - 1;

        if (alength < 0 || blength < 0)
            return "";

        if (a.substring(alength).equals(b.substring(blength))) {
            return longestCommonSubsequence(a.substring(0, alength), b.substring(0, blength))
                    + a.substring(alength);
        } else {
            String first = longestCommonSubsequence(a, b.substring(0, blength));
            String second = longestCommonSubsequence(a.substring(0, alength), b);
            if (first.length() > second.length()) {
                return first;
            } else {
                return second;
            }
        }
    }

【讨论】:

  • 感谢您的解决方案。我编辑了我的代码,但它仍然没有工作。除了那个 stackflowerror 我想问为什么从字符串的开头检查表单不起作用?
  • @Amber 你不应该在上面的代码中得到任何 stackoverflow 错误。你可以发布测试用例吗?即使您在字符串的开头找到匹配项,也不能保证它会成为 LCS 的一部分。
  • 我已经发布了。错误出现在第 5 行,我想不出原因。
【解决方案2】:

您应该将a.substring() 更改为a.charAt()

public static String LCS_r(String a, String b) {
    int m = a.length() - 1;
    int n = b.length() - 1;

    if (m < 0 || n < 0)
        return "";

    if (a.charAt(m)==b.charAt(n)) {
        return LCS_r(a.substring(0, m), b.substring(0, n)) + a.substring(m);
    } 
    else {
        String s1 = LCS_r(a, b.substring(0, n));
        String s2 = LCS_r(a.substring(0, m), b);
        if (s1.length() > s2.length()) {
            return s1;
        } else {
            return s2;
        }
    }

【讨论】:

    猜你喜欢
    • 2011-02-25
    • 2021-11-04
    • 2016-04-11
    • 2011-03-01
    • 2021-12-03
    • 2013-02-13
    • 1970-01-01
    • 2014-08-24
    相关资源
    最近更新 更多