确定Pearson Hash的完美哈希查找表

时间:2009-09-08 22:37:35

标签: algorithm hash hashtable pearson perfect-hash

我正在开发一种编程语言,在我的编程语言中,我将对象存储为哈希表。我正在使用的哈希函数是Pearson Hashing,它取决于256位查找表。这是功能:

char* pearson(char* name, char* lookup)
{
    char index = '\0';
    while(*name)
    {
        index = lookup[index ^ *name];
        name++;
    }
    return index;
}

我的问题是,给定一个少于256个成员名称的固定组,如何确定lookup表,pearson()将从{{1}开始在连续范围内返回唯一字符}。换句话说,我需要一个算法来为perfect hash创建一个查找表。这将允许我拥有不占用其成员数量的空间的对象。这将在编译时完成,因此速度不是一个大问题,但速度会更快。这很容易暴力,但我认为(希望)有更好的方法。

这是一个例子:在一个类中给定成员变量'foo','bar'和'baz',我想确定一个'\0',以便:

lookup

请注意,订单无关紧要,因此以下结果也是可以接受的:

pearson('foo',lookup) == (char) 0
pearson('bar',lookup) == (char) 1
pearson('baz',lookup) == (char) 2

在理想的世界中,表中没有的所有名称都会返回大于2的值,因为这样可以避免检查,甚至可能避免存储成员名称,但我不认为这是可能,所以我将不得不添加一个额外的检查,看看它是否在表中。鉴于此,它可能会节省不在初始化未使用的查找表中的值的时间(冲突无关紧要,因为如果它碰撞并且检查失败,则它根本不在对象中,因此碰撞不需要解决;只需要处理错误。)

3 个答案:

答案 0 :(得分:3)

看看这个page about minimal perfect hashes - 它引用了一些实现,并且有一个简短的部分,其中包含一些关于最小完美Pearson哈希的想法。

答案 1 :(得分:1)

如果成员名称太多,我强烈怀疑你能用蛮力找到解决方案。由于生日悖论,不存在碰撞的概率(即,两个散列相同)对于64而言大约是1:5000,对于96个成员名称是大约1:850,000,000。从你的哈希函数的结构(它来自一个旨在“混合”事物的加密结构)我不希望存在解决你的问题的算法(但我肯定会对这样的野兽感兴趣)。

你的理想世界是一种幻觉(如你所料):你可以追加到'foo'的256个字符,其中没有两个字符给出一个具有相同散列的新单词。由于散列值只有256种可能性,因此您可以将一个字符附加到'foo',以使其散列与'foo','bar'或'baz'的任何散列相同。

为什么不使用像CMPH这样的现有库?

答案 2 :(得分:0)

如果我理解正确,你需要的是一个可以进行二进制搜索的有序和无重复元素数组。如果密钥在数组中,则索引是“哈希”。否则,您将获得数组的大小。它是O(nlogn)与查找表O(1)的比较,但对于少量元素(在你的情况下为256)就足够了。