存储内存占用少的大字典+快速查找的方法(在Android上)

时间:2010-02-16 21:52:34

标签: java android algorithm data-structures complexity-theory

我正在开发一款需要大量(~25万字词典)的安卓文字游戏应用程序。我需要:

  • 合理快速查找,例如恒定的时间更可取,有时需要每秒进行200次查找以解决单词拼图,并且可能在0.2秒内更频繁地查找20次以查看用户拼写的单词。

编辑:查询通常会问“在字典中吗?”。我想在这个单词中支持最多两个通配符,但这很容易,只需生成通配符可能存在的所有可能的字母并检查生成的单词(即26 * 26查找带有两个通配符的单词)

  • 因为它是一个移动应用程序,使用尽可能少的内存并且只需要很少的初始下载字典数据是首要任务。

我的第一次天真尝试使用了Java的HashMap类,这导致了内存不足异常。我已经研究过使用Android上可用的SQL lite数据库,但这看起来有点过分了。

什么是做我需要的好方法?

7 个答案:

答案 0 :(得分:18)

你可以用更低级的方法实现你的目标......如果它是一个文字游戏,那么我怀疑你正在处理27个字母字母。因此,假设一个不超过32个字母的字母表,即每个字母5位。您可以使用5位/字母的简单编码将12个字母(12 x 5 = 60位)填充到单个Java long 中。

这意味着实际上如果你没有超过12个字母/单词的单词,你可以将你的字典表示为一组Java长。如果你有250,000个单词,这个集合的一个简单的表示作为单个,排序的longs数组应该需要250,000字x 8字节/字= 2,000,000~2MB内存。然后通过二分搜索进行查找,考虑到数据集的小尺寸,这应该非常快(少于20次比较,因为2 ^ 20会使你超过一百万)。

如果你的单词长于12个字母,那么会将> 12个字母单词存储在另一个数组中,其中1个单词将以明显的方式由2个连接的Java long表示。

注意:这个工作原因并且可能比trie更节省空间并且至少非常简单地实现的原因是字典是常量的...如果你需要修改数据集,搜索树是好的,但是如果数据集是常量,您通常可以使用简单的二进制搜索方式运行。

答案 1 :(得分:3)

我假设您要检查给定的单词是否属于字典。

看看bloom filter

布隆过滤器可以执行“X属于预定义集合”类型的查询,具有非常小的存储要求。如果查询的答案是肯定的,那么它的概率很小(且可调整)是错误的,如果查询的答案为否,则答案保证是正确的。

根据维基百科的文章,你的字典可能需要不到4 MB的空间,以及250%的单词,错误概率为1%。

如果单词实际包含在字典中,则布隆过滤器将正确回答“在字典中”。如果字典没有这个单词,布隆过滤器可能会错误地给出答案“在字典中”,但概率很小。

答案 2 :(得分:3)

存储目录的一种非常有效的方法是Directed Acyclic Word Graph(DAWG)。

以下是一些链接:

答案 3 :(得分:0)

你会想要某种trie。我认为也许ternary search trie会很好。它们提供非常快速的查找和低内存使用。 This paper提供了有关TST的更多信息。它还讨论了排序,因此并非所有这些都适用。 This article可能会更适用。正如文章所说,TSTs

  

结合数字时间效率   尝试空间效率   二叉搜索树。

this表所示,查找时间与使用哈希表非常相似。

答案 4 :(得分:0)

您也可以使用Android NDK并使用C或C ++进行结构。

答案 5 :(得分:0)

我工作的设备基本上是从二进制压缩文件开始工作的,其拓扑结构类似于二叉树的结构。在叶子上,你会得到Huffmann压缩文本。查找节点将涉及必须跳到文件的各个位置,然后只加载真正需要的部分数据。

答案 6 :(得分:0)

“Antti Huima”试图存储词典单词using long的建议非常酷。然后使用二分搜索进行搜索。