最长共同增加子序列动态规划

时间:2016-01-26 01:24:49

标签: c++ c algorithm recursion dynamic-programming

我正在努力寻找最长的常见增长子序列问题的解决方案。如果你不熟悉它,这是一个链接。 LCIS

问题基本上可以归结为两个不同的问题。 '最常见的子序列'和'最长的后续子序列'。这是最长公共子序列的递归解决方案:

LCS(S,n,T,m)
{
if (n==0 || m==0) return 0;
if (S[n] == T[m]) result = 1 + LCS(S,n-1,T,m-1); // no harm in matching up
else result = max( LCS(S,n-1,T,m), LCS(S,n,T,m-1) );
return result;
}

基于此和找到的一般递归公式here我一直在尝试实现算法,因此我可以使用动态编程。

int lcis(int S[4], int n, int T[4], int m, int prev)
{
  int result;

  if (n == 0 || m  == 0)
    return 1;
  if (S[n] == T[m] && S[n] > S[prev]){
    result = myMax(1 + lcis(S, n-1, T, m-1, n), lcis(S, n-1, T, m, prev),
                    lcis(S, n, T, m-1, prev)) ;
  }
  else
    result = max(lcis(S,n-1,T,m, prev), lcis(S,n,T,m-1, prev));

  return result;
}

显然这没有给出正确的解决方案。任何帮助,将不胜感激。

例如,如果我给它两个序列{1,2,4,5}和{12,1,2,4},我得到2的输出。这里的正确输出将是3,对于sub序列{1,2,4}

编辑:

以下是一些经过修改的代码,经过以下建议。仍然不是100%正确。但更接近。注意我现在使用向量,但这不应该改变任何东西。

int lcis(vector<int> S, int n, vector<int> T, int m, int size)
{
  int result;

  if (n < 0 || m < 0)
    return 0;
  if (S[n] == T[m] && (n == size - 1 || S[n] < S[n + 1] )){
    result = myMax(1 + lcis(S, n - 1, T, m - 1, size), lcis(S, n - 1, T, m, size),
                    lcis(S, n, T, m - 1, size));
  }
  else
    result = max(lcis(S, n-1, T, m, size), lcis(S, n, T, m-1, size));

  return result;
}

1 个答案:

答案 0 :(得分:1)

请记住,你要向后穿过数组。所以这个测试

 S[n] > S[prev]

应该是相反的方式:

 S[n] < S[prev]

我不确定你为什么需要上一个,因为它应该总是n + 1,所以也许可以使用

if (S[n] == T[m] && n < 3 && S[n] < S[n+1])

如果你需要让它适用于任何尺寸,那么要么通过尺寸,要么只是一个标志,说不要检查n + 1

编辑:

我的错误 - 您希望在n == 3(或大小)时遇到第一个if情况,因为您处于(可能)增加的子序列的开始。

if测试应该是

if (S[n] == T[m] && (n == 3 || S[n] < S[n+1]))

请注意,如果测试:

if (n == 0 || m  == 0)
    return 1;

忽略任一序列的第一个元素(假设它在增加的子序列的末尾)。当你在任一序列开始之前离开时,需要停止递归。您还知道,当您在序列开始之前离开时,您可能不在子序列中,因此您可以返回0作为子序列的长度。所以测试应该是

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