Backstory(跳到数据结构部分的倒数第二段):我正在研究压缩算法(LZ77种类)。该算法归结为找到给定字符串与已经看到的所有字符串之间的最长匹配。
为了快速完成这项工作,我使用了一个哈希表(带有单独的链接)as recommended in the DEFLATE spec:我一次一个地插入每个字符串(每个输入字节一个) m 每个哈希码的链中的插槽。插入很快(没有条件逻辑的常量时间),但搜索速度很慢,因为我必须查看O( m )字符串才能找到最长匹配。因为我在一个典型的例子中做了成千上万的插入和成千上万的查找,如果我想让我的算法快速运行,我需要一个高效的数据结构(目前它对于 m >来说太慢了。 4;我希望 m 更接近128)。
我已经实现了一个特殊情况,其中 m 为1,它运行非常快但是只提供一般的压缩。现在我正在为那些喜欢提高速度压缩比的人开发算法,其中 m 越大,压缩效果越好(显然)。不幸的是,到目前为止,我的尝试对于压缩比的适度增加来说太慢了,因为 m 增加了。
所以,我正在寻找一种允许非常快速插入的数据结构(因为我做了比搜索更多的插入),但仍然是相当快的搜索(优于O( m ))。是否存在O(1)插入和O(log m )搜索数据结构?如果不这样做,最好的数据结构是什么?我愿意牺牲记忆力来提高速度。我应该在我的目标平台上添加它,跳转(ifs,循环和函数调用)非常慢,堆分配(我必须使用原始字节数组自己实现所有内容以获得可接受的性能)。
到目前为止,我已经考虑过按顺序存储 m 字符串,这样可以使用二进制搜索进行O(log m )搜索,但是插入也变为O(log m )。
谢谢!
答案 0 :(得分:3)
您可能对此匹配结构感兴趣:
http://encode.ru/threads/1393-A-proposed-new-fast-match-searching-structure
是O(1)插入时间和O(m)查找。但是(m)比标准哈希表低很多倍,以获得等效的匹配结果。例如,在m = 4的情况下,此结构获得的结果与80-probe哈希表相同。
答案 1 :(得分:1)
您可能需要考虑使用trie (aka prefix tree)而不是哈希表。
对于您的特定应用程序,您可以另外优化插入。如果您知道在插入ABC
之后您可能会插入ABCD
,那么请保留对ABC
创建的条目的引用,并将其扩展为D
---无需重复查找前缀。
答案 2 :(得分:0)
哈希表中的一个常见优化是将您刚找到的项目移动到列表的头部(并且认为它可能很快会再次用于该存储桶)。也许你可以使用这个想法的变体。
如果在执行查找之前执行了所有插入操作,则可以向每个存储桶添加一个位,以指示该存储桶的链是否已排序。在每次查找时,您都可以检查该位以查看存储桶是否已排序。如果没有,您将对存储桶进行排序并设置该位。对存储桶进行排序后,每次查找都为O(lg m)。
如果交错插入和查找,则每个存储桶可以有2个列表:一个已排序,而不是。插入将始终转到未排序的列表。查找将首先检查已排序的列表,并且只有当它不存在时才会查看未排序的列表。当它在非排序列表中找到时,您将删除它并将其放入排序列表中。这样,您只需付费即可对您查找的项目进行排序。