我有一个巨大的多字节序列列表(让我们称之为单词)我需要存储在一个文件中,我需要能够快速查找。巨大意味着:大约200万个,每个长度为10-20个字节。
此外,每个单词都应该有一个标记值,这样我就可以用它来引用每个项目的更多(外部)数据(因此,拼写检查词典在这里不起作用只提供命中测试。)
如果这只是在内存中,并且内存很多,我可以简单地将所有单词存储在散列映射(也就是字典,也就是键值对)中,或者存储在二进制搜索的排序列表中。
但是,我想高度压缩数据,并且也不想将数据读入内存,而是在文件内部进行搜索。
由于单词主要基于英语,因此单词中某些“sillables”出现的可能性比其他单词更高 - 这可能对高效算法有帮助。
有人能指出我有效的技术或算法吗?
甚至代码示例?
更新
我认为DAWG或任何类似路径将这条路径路径化为常用后缀对我来说不起作用,因为那时我将无法用单个值标记每个完整的单词路径。如果我要检测常见的后缀,我必须将它们放入自己的字典(查找表)中,以便trie节点可以引用它们,但节点将保留其自己的结束节点以存储该路径的标记值。
事实上,这可能是要走的路:
我可以尝试找到经常使用的字符序列,并为这些字符序列创建一个节点,而不是仅为单个字符构建树节点。这样,单个节点可以覆盖多个字符,可能会导致更好的压缩。
现在,如果这是可行的,我将如何在我的所有短语中找到经常使用的子序列? 大约有200万个短语通常由1-3个单词组成,所有可能的子串的所有排列都很难...
答案 0 :(得分:7)
存在称为trie的数据结构。我相信这种数据结构非常适合您的要求。基本上,trie是一棵树,其中每个节点都是一个字母,每个节点都有子节点。在基于字母的trie中,每个节点将有26个孩子。
根据您使用的语言,创建时可能更容易或更好地存储为可变长度列表。
这种结构给出: a)快速搜索。在长度为n的单词后面,您可以在树中找到n个链接中的字符串。 b)压缩。存储公共前缀。
示例:单词BANANA和BANAL都将具有相等的B,A,N,A节点,然后最后一个(A)节点将具有2个子节点L和N.您的节点还可以存储有关该单词的其他信息。
(http://en.wikipedia.org/wiki/Trie)
Andrew JS
答案 1 :(得分:2)
我建议使用Trie或DAWG(有向无环字图)。斯坦福大学有一个很棒的讲座,就是在这里完成你想做的事:http://academicearth.org/lectures/lexicon-case-study
答案 2 :(得分:1)
查看论文"How to sqeeze a lexicon"。它解释了如何构建一个最小化的有限状态自动机(这只是DAWG的另一个名称),它将字与数字一对一映射,反之亦然。正是你需要的。
答案 3 :(得分:0)
您应该熟悉索引文件。
答案 4 :(得分:0)
您是否尝试过使用哈希映射?事实上,在现代操作系统架构中,操作系统将使用虚拟内存将未使用的内存段交换到磁盘。因此,结果只是将其全部加载到哈希映射中实际上是有效的。
正如jkff指出的那样,你的列表只有大约40 MB,这并不是那么多。