【问题标题】:Error in Recursive solution to Longest Common Substring最长公共子串的递归解法错误
【发布时间】:2018-06-23 19:57:50
【问题描述】:

问题:给定两个字符串“X”和“Y”,求最长公共子串的长度。
我的解决方案继续运行并且没有达到基本条件。我不明白这是为什么?

我查看了 DP 解决方案,但在 Internet 上找不到此问题的令人满意的递归解决方案。

int lcs_calc(string str1, string str2, int i_1, int i_2, int lcs, int c_lcs)
{

    if (i_1 >= str1.length() || i_2 >= str2.length())
    {
        //end. base cond
        return lcs;
    }
    if (str1[i_1] == str2[i_2])
    {
        c_lcs++;
        if (c_lcs > lcs) lcs = c_lcs;
        return lcs_calc(str1, str2, ++i_1, ++i_2, lcs, c_lcs);
    }
    else
    {
        if (c_lcs == 0)
        {
            return max(lcs_calc(str1, str2, ++i_1, i_2, lcs, c_lcs), lcs_calc(str1, str2, i_1, ++i_2, lcs, c_lcs));
        }
        else
        {
            c_lcs = 0;
            return max(lcs_calc(str1, str2, --i_1, i_2, lcs, c_lcs), lcs_calc(str1, str2, i_1, --i_2, lcs, c_lcs));
        }


    }
}



初始参数:

str1 = "AABC"
str2 = "ABCD"

i_1 = 0(第一个字符串的索引)
i_2 = 0(第二个字符串的索引)
c_lcs = 0(当前公共子串的长度)
lcs = 0(最长公共子串的长度)

【问题讨论】:

  • 您是否尝试过在调试器中单步执行代码?使用递归函数可能会很麻烦,尤其是当你有尽可能多的调用时,但这仍然是每个程序员都需要能够做的事情。
  • 我认为你永远不会达到你的基本条件,除非其中一个字符串是另一个字符串的子字符串(尝试使用“ABC”和“AABCDE”) - 假设没有其他问题你的代码,应该很好地终止。您需要制定不同的基本条件。
  • 字符串是按值传入的,那为什么还要有 i_1 和 i_2 呢?为什么不改变字符串并检查 s[0] == p[0] 是否通过执行 s.substr(1) 和 p.substr(1) 如果不跳过 s[i] 并检查跳过 p[一世]。在基本情况下 s.empty 或 p.empty 返回 1 并添加它。你让这变得非常复杂。
  • 顺便说一句,您是在longest common substring 还是longest common subsequence 之后,上述尝试似乎指向后者。

标签: c++ recursion substring dynamic-programming


【解决方案1】:
return max(lcs_calc(str1, str2, ++i_1, i_2, lcs, c_lcs), lcs_calc(str1, str2, i_1, ++i_2, lcs, c_lcs));

在第一次调用中,只有i_1 应该递增,而在第二次调用中,只有i_2 应该递增。由于您使用++,递增的i_1 会在两个调用中传递。 你应该明白,一旦你在第一次调用中执行++i_1,在第二次调用lcs_calc()i_1 时也会作为递增值传递,这不是你想要的。

另外,你不需要其他情况。

else
{
 return max(lcs_calc(str1, str2, i_1+1, i_2, lcs, c_lcs), lcs_calc(str1, str2, i_1, i_2+1, lcs, c_lcs));
}

【讨论】:

  • 谢谢。我之前也犯过同样的增量错误。这很好用。
  • 我们还需要在else部分重置c_lcs,对吗?
【解决方案2】:

令人惊讶的是,您在递归调用函数时减少了索引。不应该这样做,因为返回时索引会自动减少。您应该继续增加一个索引,然后当字符不同时继续增加另一个索引。

类似的东西(关注递归,而不是正确性):

if (length reached): return c_lcs
if same: lcs = rec(str1, str2, i1+1, i2+1, c_lcs)
lcs = max(lcs, rec(str1, str2, i1+1, i2, 0))
lcs = max(lcs, rec(str1, str2, i1, i2+1, 0))
return lcs;

【讨论】:

  • 您最好使用 i1+1 等代替或 ++i1。看起来您当前的代码受到 ++ 副作用的负面影响
  • 正确,我接管了问题的增量,修复。
猜你喜欢
  • 2014-08-24
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 1970-01-01
  • 2014-04-14
  • 2021-12-03
相关资源
最近更新 更多