没有数组的记忆


14

在Cormen等人的“算法简介”中,第15.3节动态编程的元素对记忆的解释如下:

记忆的递归算法为每个子问题的解决方案在表中维护一个条目。每个表条目最初都包含一个特殊值,以指示该条目尚未填写。当递归算法展开时,第一次遇到子问题时,将计算其解决方案,然后将其存储在表中。以后每次遇到此子问题时,我们只需查找表中存储的值并返回它。

并且添加了一个脚注:

这种方法的前提是我们知道所有可能的子问题参数的集合,并且已经建立了表位置和子问题之间的关系。另一种更通用的方法是通过使用以子问题参数作为键的哈希来记忆。

是否有任何众所周知的DP问题需要(或使其更容易)将已存储的值存储在字典中,而不是在(多维)数组中?


背景:如果有什么用,这个问题的原因是我正试图将(自平衡)二进制搜索树的概念激发给刚刚看过动态编程的人们。


在我使用的真实软件中,记忆可以利用以下事实:可以从代码中的许多不同位置调用相对昂贵的函数(如explogpow),并经常被多次调用。每个特定代码位置的值相同。在那种情况下,“字典”可以是存储在特定于代码位置的变量中的单个值。
Mike Dunlavey

Answers:


5

也许有更好的例子,但这是我脑海中的一个例子:

小号Ťd>d


3

我想提供2个例子。

0-1背包问题

如果是0-1背包问题(其中W是背包的容量,N是物品的数量),有时最好使用自上而下的带有记忆的动态编程,而不是系统的自下而上的枚举大小为WxN的整个2D数组的数组(特别是在背包W的容量很大,但允许的项目重量组合的集合的基数远小于W的情况下)。

在这种情况下,为了节省存储器,可以选择使用词典进行记忆,而不是使用2D数组。

Earley解析算法

Earley解析算法可用于语句的解析,这些语句属于无上下文语法。与CYK算法(基于自底向上的DP方法并使用2D表进行记录)相对,Earley解析器将自上而下的方法与解析表结合使用来进行记录。

解析表包含部分解析的语法产生式(例如:给定产生式X→AB,并且在成功匹配该产生式的A部分之后,我们将部分匹配的产生式存储在解析图内部:X→A•B,其中点到已经匹配的部分)。

解析图表中的列数等于令牌数。但是,在一般情况下,估计每列部分解析的语法产生量可能非常棘手(取决于语法和特殊的标记顺序)。

因此,基于字典数据结构实现解析图更加方便。

在自然语言处理域中,通常Earley分析器是更方便的选择,因为它不需要语法的Chomsky范式(而CYK确实有此要求)。


0

根据我在竞争性编程中的经验,使用哈希表(Python dict或类似表)通常比使用数组更方便,因为任何可哈希数据类型都可以用作键,例如字符串,集合(frozenset在Python中)或类似tuple的元组等(string, int)。如果使用数组,则必须手动将所有键转换为整数(从0开始),这需要额外的工作,并且如您的原始资料所述,如果您事先不知道键的空间,则可能无法实现。因此,字典比数组更通用。

当然,如果您可以避免使用数组,那么它可能会更快,因为它避免了重复计算哈希(另一方面,它要求首先初始化整个数组,这需要时间和内存),但是编写代码可能会花费更长的时间。因为您必须完成将所有键转换为整数的额外工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.