【问题标题】:What's a good hash function for English words?什么是英语单词的好散列函数?
【发布时间】:2011-12-03 18:20:48
【问题描述】:

我有一长串英语单词,我想对它们进行哈希处理。什么是好的散列函数?到目前为止,我的散列函数将字母的 ASCII 值相加,然后对表格大小取模。我正在寻找高效且简单的东西。

【问题讨论】:

标签: c++ c hash


【解决方案1】:

简单地将字母相加并不是一个好的策略,因为排列会产生相同的结果。

这个 (djb2) 非常流行,可以很好地处理 ASCII 字符串。

unsigned long hashstring(unsigned char *str)
{
    unsigned long hash = 5381;
    int c;

    while (c = *str++)
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

    return hash;
}

更多信息here

如果您需要更多替代方案和一些性能指标,请阅读here

补充:这些是一般散列函数,其中输入域是事先不知道的(除了一些非常一般的假设:例如,上面的内容与 ascii 一起工作得更好一些输入),这是最常见的情况。如果您有一个已知的受限域(固定输入集),您可以做得更好,请参阅 Fionn 的回答。

【讨论】:

  • 不,它只是一个“种子”,相当随意。
  • @MikeG:这是“种子”或起始值。这个通常称为“Times 33”哈希。
  • @sixlettervariables 我在哪里指定表格长度?如果它返回的数字大于我的表格怎么办?
  • 理论上它可以返回任何有效的unsigned long值。由您来操作散列以适应您的约束。
  • @MikeG:通常,您不会在哈希算法中指定表大小(如果您不知道,请使用已经制作的表......)。该表可能会根据项目的数量而增长或缩小(对于良好的实现),因此您只需计算哈希值,然后将哈希值取模当前大小即可知道将其放入哪个存储桶中。
【解决方案2】:

也许这样的事情会帮助你:http://www.gnu.org/s/gperf/

它为输入域生成一个优化的散列函数。

【讨论】:

    【解决方案3】:

    如果您不需要加密安全,我建议使用 Murmur Hash。它速度极快,并且具有很高的扩散性。易于使用。

    http://en.wikipedia.org/wiki/MurmurHash

    http://code.google.com/p/smhasher/wiki/MurmurHash3

    如果您确实需要加密安全哈希,那么我建议通过 OpenSSL 进行 SHA1。

    http://www.openssl.org/docs/crypto/sha.html

    【讨论】:

    • MurmurHash+1,你知道 CityHash 和 MurmurHash 的比较吗?我听说过两者的好消息,但从未见过全面的比较,只是有一些轶事。
    【解决方案4】:

    有点晚了,但这里有一个哈希函数,对于下面的 64 位版本,冲突率极低,并且 ~ 几乎 ~ 对 32 位版本同样好:

    uint64_t slash_hash(const char *s)
    //uint32_t slash_hash(const char *s)
    {
        union { uint64_t h; uint8_t u[8]; } uu;
        int i=0; uu.h=strlen(s);
        while (*s) { uu.u[i%8] += *s + i + (*s >> ((uu.h/(i+1)) % 5)); s++; i++; }
        return uu.h; //64-bit
        //return (uu.h+(uu.h>>32)); //32-bit
    }
    

    哈希数也非常均匀地分布在可能的范围内,没有我可以检测到的聚集 - 这仅使用随机字符串进行检查。
    [编辑]
    还针对从本地文本文件中提取的单词以及 LibreOffice 词典/同义词库单词(英语和法语 - 超过 97000 个单词和结构)进行了测试,在 64 位中出现 0 次冲突,在 32 位中出现 1 次冲突-位:)

    (还与 FNV1A_Hash_Yorikke、djb2 和 MurmurHash2 在同一组上进行比较:Yorikke 和 djb2 表现不佳;slash_hash 在所有测试中都略好于 MurmurHash2)

    【讨论】:

    • 这是一个合理的哈希函数。我建议避免使用未命名的工会。 -->> union { uint64_t h; uint8_t u[8]; } uu; 和代码中的类似更改 -->> uu.h=strlen(s); ... uu.u[i%8] += ...
    猜你喜欢
    • 2017-10-15
    • 2015-10-10
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    相关资源
    最近更新 更多