用于存储单词列表的节省空间的数据结构?
对于这种情况,还有比Trie更好的东西吗?
- 存储~100k英文单词列表
- 需要使用最少的内存
- 查找需要合理,但不必快速闪电
我正在使用Java,所以我的第一次尝试就是使用Set 。 但是,我的目标是移动设备并且内存不足。 由于许多英语单词共享共同的前缀,trie似乎是一个体面的赌注,以节省一些记忆 – 任何人都知道一些其他好的选择?
编辑 – 更多信息 – 数据结构将用于两个操作
- 回答:列表中是否有XYZ字样?
- 生成XYZ周围的单词邻域,其中一个字母不同
谢谢你的好建议
你在做什么? 如果是拼写检查,你可以使用布隆filter – 请参阅此代码kata 。
我在拼写字典中最小化空间时看到的一种结构是将每个单词编码为:
- 与最后一个共同的字符数(一个字节); 和
- 新的结局。
所以单词列表
HERE would encode as THIS sanctimonious 0,sanctimonious sanction 6,on sanguine 3,guine trivial 0,trivial
你在那里直接保存7个字节(19%),我怀疑由于相邻单词的(公共前缀)之间的最小距离,对于20,000字的字典保存是相似的。
为了加速查找,内存中有一个26条目表,它保存以a,b,c,…,z开头的单词的起始偏移量。 这些偏移处的字总是以0作为第一个字节,因为它们没有与前一个字相同的字母。
这似乎是一种特里但没有指针,如果树中的每个字符都有一个与之关联的4字节指针,这肯定会占用太多空间。
请注意,这来自我的CP / M日,那里的记忆比现在更加稀缺。
您仍然需要使用Trie维护树结构。 编码字母或N字母的霍夫曼 (对于“ing”,“un”,“ing”等常见forms)可以利用字典中的出现频率并将条目压缩为位。
完全疯狂的想法……(也就是说非常错误)
如何将单词存储为所有可能的字母组合的树?
然后每个“单词”只花费一个char和两个指针(一个指向char,一个指向终结符。)这样,它们共有的字母越多,每个单词的成本就越少。
. . / / rps-. /\\ a \s-. / t-. c \ s-.
汽车鲤鱼鲤鱼汽车推车
因此,对于9个字符和14个指针,我们得到6个“单词”,总共25个字母。
搜索会很快(指针查找而不是字符比较),你可以做一些词干优化来节省更多的空间……?
编辑:看起来我重新发明了轮子。 😉
与保罗的post有关:
在你的情况下你不能考虑Trie的任何理由? 如果它只是一个实现问题,这里是Patricia trie插入和C搜索(来自NIST)的紧密实现:
Patricia插入C语言
Patricia在C中搜索