3

我有一个词汇,, a, abandon... , z.

出于某种原因,我将使用数组而不是 Trie 来存储它们。

因此,一个简单的方法可以是:wordA\0wordB\0wordC\0...word\0

但我认为还有一些更经济的记忆方法。

由于like是 的子串likely,我们只能存储第一个位置和长度,like而不是字符串本身。因此,我们生成了一个“大字符串”,其中包含词汇表中的每个单词并使用position[i]length[i]获得第i-th 个单词。

例如,词汇表包含三个单词ab和。我构造为“大字符串”。cdbcabcd

position[0] = 0, length[0] = 2

position[1] = 2, length[1] = 2

position[2] = 1, length[2] = 2

那么如何生成“大字符串”是这个问题的关键,有什么很酷的建议吗?

我认为这个问题类似于TSP问题(Traveling Salesman Problem),是一个NP问题。

4

1 回答 1

0

您要查找的搜索关键字是“字典”。即可用于存储单词列表的数据结构,并测试字典中是否存在其他字符串。


您的想法比单独存储每个单词更紧凑,但不如 DAWG 之类的良好数据结构紧凑。正如您所注意到的,如何最佳地选择如何重叠您的字符串并不明显。你所做的有点像无损压缩方案(如 gzip)所做的。如果您不需要根据紧凑型词典检查单词,也许只需使用 gzip 或 LZMA 来压缩排序的单词列表。让他们的算法找到冗余并紧凑地表示它。

我在字典中查找了引起我兴趣的最近的 SO 答案:Memory-constrained external sort of strings, with duplicates combined&counted, on a critical server (billions of filenames)

对于不必即时添加新词的字典,有向无环词图是可行的方法。您可以通过跟踪图形节点来匹配一个字符串,直到您到达没有与下一个字符匹配的边缘的点,或者您到达输入字符串的末尾并发现 DAWG 中的节点被标记为有效结束词。(而不仅仅是一个子字符串,它只是某些单词的前缀)。有一些算法可以在合理的时间内从一个简单的单词数组字典构建这些状态机。

只有当整个单词是另一个单词的子字符串,或者一个单词的结尾,另一个单词的开头时,您的方法才能利用冗余。DAWG 可以在任何地方利用常见的子字符串,并且匹配单词的速度也非常快。可能与二进制搜索数据结构的速度相当,尤其是。如果巨型字符串太大而无法放入缓存中。(一旦开始超过缓存大小,数据结构的紧凑性开始超过代码复杂性以提高速度。)

不太复杂但仍然有效的是Trie(或Radix Trie),其中合并了公共前缀,但单词后面的公共子字符串不会再次收敛。

如果您根本不需要修改您的 DAWG 或 Trie,您可以将其高效地存储在单个内存块中,而不是动态分配每个节点。你没有说你为什么不想使用 Trie,也没有承认存在比普通 Trie 做得更好的其他数据结构。

于 2015-11-16T09:49:42.867 回答