我有一个关于优化常见动态编程任务的内存的问题:找到两个字符串的最长公共子序列。我找到了一个response to a similar question,它有响应
请注意,当您计算表格中的下一行时 动态编程解决方案解决LCS问题,您只需要 上一行和当前行。然后你可以修改动态 编程解决方案只跟踪前一行和 当前行而不是m x n表。每次你到达终点 在当前行中,您将上一行设置为当前行,并且 再次从行的开头开始。你这样做m次m 是表中的行数。这将使用空间线性 列数。
但我有两个问题。
首先,当您使用将上一行设置为新行时,您是否仍然拥有旧行中的值?不会影响结果吗?
其次,为什么不能对列进行相同的优化呢?也就是说,当您到达列的末尾时,将前一列设置为当前列?
答案 0 :(得分:2)
请查看有关此问题的wikipedia页面,尤其是包含表格的图表。要计算行i
和列j
中的单元格的结果,您需要在当前单元格的左侧,顶部和左上角的单元格的先前结果,因此LCS(i, j) = some_function(LCS(i-1, j), LCS(i, j-1), LCS(i-1, j-1))
。要计算所有单元格的结果(您甚至需要做出最终答案),因此更容易计算沿行或列的条带中的所有中间结果。
回答你的问题:
可以安全地重复使用行i-2
来存储行i
的新结果,因为您只是从左到右覆盖旧结果。从当前行计算单元格i, j
所需的唯一信息是单元格i, j-1
,您刚刚使用上一步中的新值进行了更新。
您可以通过各种方式填充整个表格,最终获得右下角单元格的结果。您可以逐行(标准),逐列,交替一列,然后一行或沿对角线前面填充表格。试试自己的笔和纸:画一个网格并用十字架填充整个网格,但只标记已标记相关邻居的单元格。实现逐行或逐列版本更简单,因为您只需要2个固定长度的向量来保存中间结果。