如何更有效地将词汇存储在数组中?
Posted
技术标签:
【中文标题】如何更有效地将词汇存储在数组中?【英文标题】:How to store vocabulary in an array more effectively? 【发布时间】:2016-02-17 08:43:58 【问题描述】:我有一个词汇表,a
、abandon
、...、z
。
出于某种原因,我将使用数组而不是 Trie 来存储它们。
因此一个简单的方法可以是:wordA\0wordB\0wordC\0...word\0
但我认为还有一些更经济的记忆方法。
由于like
是likely
的子串,我们只能存储like
的第一个位置和长度,而不是字符串本身。因此,我们生成了一个“大字符串”,其中包含词汇表中的每个单词,并使用position[i]
和length[i]
得到i
-th 单词。
例如,词汇表包含三个单词ab
、cd
和bc
。
我将abcd
构造为“大字符串”。
position[0] = 0, length[0] = 2
position[1] = 2, length[1] = 2
position[2] = 1, length[2] = 2
那么如何生成“大字符串”是这个问题的关键,有什么很酷的建议吗?
我认为这个问题类似于TSP问题(Traveling Salesman Problem),属于NP问题。
【问题讨论】:
有什么理由不从现有的数据库解决方案中受益?当然你可以发明你自己的。但是,值得付出努力吗? @clq:我认为关系数据库不会将字符串表压缩为 Trie 或任何东西。如果我错了,请纠正我,但是以单个字符串字段作为主键的 DB 表将为您提供非常快速的索引检查是否存在/不存在,但可能会占用 更多 空间而不是将它们全部存储回来-在 C 字符串中返回。 @clq 数组对于纯 C 项目来说更高效且易于处理。 @LTzycLT:空间效率更高,但时间效率低于使用开箱即用的数据库。数据库库将为您提供良好的性能,而无需花费大量开发时间。 trie 有什么问题?您正在谈论的结构对我来说似乎非常具有限制性……或者换一种说法:它只能在非常特定的情况下获利。你举了一个例子,其中一个词是另一个词的前缀 - “喜欢”和“可能”。但是如果他们只 share 前缀怎么办。对于即时“喜欢”和“喜欢”。你的数组应该如何有效地存储这两个词?好吧,我认为 Trie 将是完美的...... 【参考方案1】:您要查找的搜索关键字是“字典”。即可用于存储单词列表并测试字典中是否存在其他字符串的数据结构。
您的想法比单独存储每个单词更紧凑,但远不如像 DAWG 这样的良好数据结构紧凑。正如您所注意到的,如何最佳地选择如何重叠您的字符串并不明显。你所做的有点像无损压缩方案(如 gzip)所做的。如果您不需要根据紧凑型词典检查单词,也许只需使用 gzip 或 LZMA 来压缩排序的单词列表。让他们的算法找到冗余并紧凑地表示它。
我在字典中查找了最近引起我兴趣的 SO 答案:Memory-constrained external sorting of strings, with duplicates combined&counted, on a critical server (billions of filenames)
对于不必即时添加新单词的字典,Directed Acyclic Word Graph 是不错的选择。您可以通过跟踪图形节点来匹配一个字符串,直到您到达没有与下一个字符匹配的边缘的点,或者您到达输入字符串的末尾并发现 DAWG 中的节点被标记为有效结束词。 (而不仅仅是一个子字符串,它只是某些单词的前缀)。有一些算法可以在合理的时间内从一个简单的单词数组字典构建这些状态机。
只有当整个单词是另一个单词的子字符串,或者一个结尾,另一个开头时,您的方法才能利用冗余。 DAWG 可以在任何地方利用常见的子字符串,并且匹配单词的速度也非常快。可能与二进制搜索数据结构的速度相当,尤其是。如果巨型字符串太大而无法放入缓存中。 (一旦开始超过缓存大小,数据结构的紧凑性就开始超过代码复杂性以提高速度。)
不太复杂但仍然有效的是Trie(或Radix Trie),其中合并了公共前缀,但单词后面的公共子字符串不会再次收敛。
如果您根本不需要修改您的 DAWG 或 Trie,您可以将其高效地存储在单个内存块中,而不是动态分配每个节点。你没有说为什么你不想使用 Trie,也没有承认存在比普通 Trie 做得更好的其他数据结构。
【讨论】:
你读过OP的问题吗?具体来说:For some reason, I will use array rather than Trie
。他说清楚了他想用什么方法你不回答问题:how to generate the "large string"
@fjardon:哎呀,不,我在浏览时错过了。我只是在更新我的答案,以便更好地回答这个问题,或者至少指出他想要的类似于 gzip 这样的无损压缩方案(并建议使用它)。也许看看那些以获得灵感。没错,这个答案并没有直接回答 OP 提出的问题,而是试图提出一些可以以不同方式解决相同问题的建议。以上是关于如何更有效地将词汇存储在数组中?的主要内容,如果未能解决你的问题,请参考以下文章