C++ Rabin-Karp算法的最佳哈希函数是什么?

C++ Rabin-Karp算法的最佳哈希函数是什么?,c++,c,algorithm,pseudocode,rabin-karp,C++,C,Algorithm,Pseudocode,Rabin Karp,我正在为Rabin-Karp算法寻找一个有效的哈希函数。这是我的实际代码(C编程语言) static bool f2(字符常量*常量s1,大小常量n1, 字符常量*常量s2,大小常量n2) { uintmax_t hsub=散列(s2,n2); uintmax_t hs=散列(s1,n1); 尺寸nmax=n2-n1; 对于(尺寸i=0;i

我正在为Rabin-Karp算法寻找一个有效的哈希函数。这是我的实际代码(C编程语言)

static bool f2(字符常量*常量s1,大小常量n1,
字符常量*常量s2,大小常量n2)
{
uintmax_t hsub=散列(s2,n2);
uintmax_t hs=散列(s1,n1);
尺寸nmax=n2-n1;
对于(尺寸i=0;i

我考虑了一些Rabin Karp C实现,但所有代码之间都有差异。所以我的问题是:Rabin-Karp散列函数应该具有什么特征?

一个性能非常好的散列是bernstein散列。它甚至超过了 许多流行的哈希算法

unsigned bernstein_hash ( void *key, int len )
{
    unsigned char *p = key;
    unsigned h = 0;
    int i;

    for ( i = 0; i < len; i++ )
        h = 33 * h + p[i];

    return h;
}
unsigned bernstein\u散列(void*键,int len)
{
无符号字符*p=键;
无符号h=0;
int i;
对于(i=0;i
当然,您可以尝试其他哈希算法,如下所述:

注意:从未解释过为什么
33
的性能会更好 比任何其他“更具逻辑性”的常数

出于您的兴趣:下面是不同哈希算法的一个很好的比较:
对于小字母表的问题,例如核酸序列搜索(例如
字母表={A,T,C,g,U}
),可能是一个好的哈希函数。
它使用了更快的二进制运算和滚动哈希更新,还提供了统一分布的哈希值。

您已经看到了吗?Rabin Karp不能只使用任何哈希函数,它需要一个专门的哈希函数,可以从已知的位置(i-1)值快速计算位置i。是的,@Gigi,我有。但如果有更好的散列函数,它将是完美的(因为我将多次运行此函数)@rossum:根据维基百科的文章,我做了一个“重设”功能。你读过这个吗?@md5,也许md5,不管怎样,只是开个玩笑:)算术运算中“未签名”溢出可以吗?@Pupsik溢出一般不成问题,所以我会说是的。这怎么会被接受并且是一个投票率很高的答案?它的时间复杂度是O(p)。如果对主文本的每个窗口调用该函数,则模式搜索函数的时间复杂度将为O(p*t),这与蛮力方法相同。问题是关于一个与Rabin-Karp算法配合良好的哈希函数。这个函数没有,但Rabin Carp的算法暗示了使用滚动哈希函数。滚动散列函数是一种具有特殊性质的函数:例如,如果我们已经知道H(c[0..n])的值,我们可以快速计算H(c[1..n+1])。这是滚动散列函数的属性,bernstein散列没有!我认为,我们应该否决这个答案!我不知道为什么评论说这个散列函数不能有效地滚动。它相当于(模
sizeof(unsigned)
)以33为基数的字符串的伪表示。如果您的窗口有长度
k
,您可以通过用
pow(33,k-1)*str[i-k]
减去散列来从散列中“删除”
str[i-k]
。i、 e.要按1滚动散列,请执行
hash=33*(hash-pow(33,k-1)*str[i-k])+str[i]
unsigned bernstein_hash ( void *key, int len )
{
    unsigned char *p = key;
    unsigned h = 0;
    int i;

    for ( i = 0; i < len; i++ )
        h = 33 * h + p[i];

    return h;
}