使用一维数组的 LCS 动态规划

Posted

技术标签:

【中文标题】使用一维数组的 LCS 动态规划【英文标题】:LCS dynamic programming using one dimensional array 【发布时间】:2016-03-17 12:33:21 【问题描述】:

我正在尝试进行动态编程来查找 LCS 的长度。我为此使用了二维数组。但是对于一个大字符串,它会由于内存溢出而产生运行时错误。请告诉我我应该如何在一维数组中做以避免内存限制。

#include<bits/stdc++.h>
 #include<string.h> 
 using namespace std;
int max(int a, int b);
int lcs( string X, string Y, int m, int n )

   int L[m+1][n+1];
   int i, j;
   for (i=0; i<=m; i++)
   
     for (j=0; j<=n; j++)
     
       if (i == 0 || j == 0)
         L[i][j] = 0;

       else if (X[i-1] == Y[j-1])
         L[i][j] = L[i-1][j-1] + 1;

       else
         L[i][j] = max(L[i-1][j], L[i][j-1]);
     
   

   return L[m][n];


int max(int a, int b)

    return (a > b)? a : b;


int main()

  string X;
  string Y;
  cin>>X>>Y;
  int m = X.size();
  int n = Y.size();

  printf("Length of LCS is %d\n", lcs( X, Y, m, n ) );

  return 0;

【问题讨论】:

[OT] int L[m+1][n+1]; 使用变长数组扩展,更喜欢使用std::vector vector 也为 500k 左右的输入字符串提供运行时错误 棘手;你可能需要调整Hirshberg’s algorithm 来解决这个问题。这是可行的,但绝对比简单的 LCS 算法复杂得多(编辑:啊,你只对长度感兴趣,而不是实际的子序列;这要容易得多,请参阅 Sergei 的答案)。不相关的是,您肯定需要使用vector 而不是变长数组;另外,打开编译器警告(GCC 和 clang 上的-Wall -Wextra)并使你的编译器变得迂腐(GCC 和 clang 上的-pedantic)。 【参考方案1】:

注意lcs 中的递归仅使用L 矩阵的最后两行。因此,您可以轻松地重写您的解决方案以使用 O(N) 内存。

这里有一个关于这个主题的good article。

【讨论】:

【参考方案2】:

二维数组无论如何都是虚构的,它仍然是一维数组,所以你自己计算索引,即:所以你的数组 int L[(n+1)(m+1)] 和索引 L[ i][j] = L[i(n+1)+j]

【讨论】:

以上是关于使用一维数组的 LCS 动态规划的主要内容,如果未能解决你的问题,请参考以下文章

0/1 背包动态规划优化,从二维矩阵到一维矩阵

经典动态规划——0/1背包问题(二维数组动规,一维数组动规实现)

动态规划 学习笔记

左程云-递归和动态规划

带一维数组的动态编程 USACO 培训:子集总和

数据结构与算法学习——动态规划-3