当前位置: 首页 > 知识库问答 >
问题:

最长公共递增子序列动态规划

冯翔
2023-03-14

我正在寻找最长的常见递增子序列问题的解决方案。如果你不熟悉,这里有一个链接。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;
}

基于此和这里找到的一般递归公式,我一直在尝试实现该算法,以便可以使用动态规划。

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的输出。对于子序列{1,2,4},这里的正确输出是3

编辑:

下面是一些经过修改的代码,根据下面的建议。仍然不是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个答案

聂翼
2023-03-14

请记住,您正在向后穿过数组。所以这个测试

 S[n] > S[prev]

反之亦然:

 S[n] < S[prev]

我不知道为什么你需要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测试:

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

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

if (n < 0 || m < 0)
    return 0;
 类似资料:
  • 我正在复习在寻找两个等长字符串的最长公共子序列的上下文中讨论动态规划的笔记。有问题的算法输出长度(而不是子字符串)。 所以我有两个字符串,说: S=ABAZDC,T=BACBAD 最长的公共子序列是ABAD(子字符串不必是相邻的字母) 算法如下,其中LCS[i,j]表示S[1..i]和T[1..j]的最长公共子序列: 我的笔记声称你可以填写一个表格,其中每个字符串都沿着一个轴写。比如: B A C

  • 在最多一个序列存在重复的情况下,可以将最长公共子序列问题转化为最长递增子序列问题。减少问题的过程说明在这里: 假设您有以下序列: 然后,创建一个整数序列S3,其中您必须将S2的每个元素的位置放在S1中(如果元素在S1中不存在,那么忽略那个元素)。在本例中: 这种方法是如何工作的?为什么这种约简解决了寻找最长公共子序列的问题?

  • 我有以下问题: 示例: 输入:[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]输出:6顺序:[0,2,6,9,13,15]或[0,4,6,9,11,15]或[0,4,6,9,11,15] 这是一个DP问题,我确实有一些问题在记忆步骤。下面是我的代码: 多谢了。

  • 我试图为最长公共子序列写一个动态规划算法。返回应该是这个子序列的长度。但是我的算法总是返回0。我找不到错误。

  • 最长递增子序列 题目描述 给定一个长度为N的数组a0,a1,a2…,an-1,找出一个最长的单调递增子序列(注:递增的意思是对于任意的i<j,都满足ai<aj,此外子序列的意思是不要求连续,顺序不乱即可)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4。 分析与解法 解法一:转换为最长公共子序列问题 比如原数组为 A{5,

  • 给定n个正整数的数组。这是一个寻找给定数组的最大和子序列的和的程序,使得子序列中的整数按升序排列。我试图实现基于这个YouTube视频的代码,我不知道我做错了什么。