生成k个成对独立的散列函数

时间:2012-08-25 08:11:22

标签: scala hash-function cryptographic-hash-function

我正在尝试在Scala中实现Count-Min Sketch算法,因此我需要生成k个成对独立的哈希函数。

这比我以前编程的任何东西都要低,除了Algorithms类之外我对哈希函数知之甚少,所以我的问题是:如何生成这些k成对独立哈希函数? / p>

我应该使用像MD5或MurmurHash这样的哈希函数吗?我是否只生成f(x) = ax + b (mod p)形式的k哈希函数,其中p是素数,a和b是随机整数? (即universal hashing family每个人都在算法101中学习

我看起来更简单而不是原始速度(例如,如果它更容易实现,我将采取5倍慢的速度。)

2 个答案:

答案 0 :(得分:4)

Scala已经实施了MurmurHash(它是scala.util.MurmurHash)。它非常快速且非常擅长分配价值。加密哈希是过度的 - 你只需要比你需要的时间长几十或几百倍。只需选择k种不同的种子,因为它的质量几乎是加密的,所以你会得到k很大程度上独立的哈希码。 (在2.10中,您应该切换到使用scala.util.hashing.MurmurHash3;使用情况有所不同,但您仍然可以通过混合执行相同的操作。)

如果你只需要将近似值映射到随机远值,这将起作用;如果你想避免碰撞(即如果A和B碰撞使用散列1它们可能也不会使用散列2碰撞),那么你需要至少再做一步并且不要散列整个对象而是散布它的子组件哈希有机会开始不同。

答案 1 :(得分:2)

可能最简单的方法是采用一些加密哈希函数,并用不同的字节序列“种子”它。对于大多数实际用途,结果应该是独立的,因为这是加密散列函数应该具有的关键属性之一(如果替换消息的任何部分,则散列应该完全不同)。

我会做类似的事情:

// for each 0 <= i < k generate a sequence of random numbers
val randomSeeds: Array[Array[Byte]] = ... ; // initialize by random sequences

def hash(i: Int, value: Array[Byte]): Array[Byte] = {
    val dg = java.security.MessageDigest.getInstance("SHA-1");
    // "seed" the digest by a random value based on the index
    dg.update(randomSeeds(i));
    return dg.digest(value);
    // if you need integer hash values, just take 4 bytes
    // of the result and convert them to an int
}

修改 我不知道Count-Min Sketch的精确要求,也许一个简单的函数就足够了,但它似乎不是最简单的解决方案。

我建议使用加密哈希函数,因为你有很强的保证,结果哈希函数将会非常不同,并且很容易实现,只需使用标准库。

另一方面,如果你有f1(x) = ax + b (mod p)f2(x) = cx + d (mod p)形式的两个哈希函数,那么你可以使用一个简单的线性公式计算一个使用另一个(不知道x)的哈希函数f2(x) = c / a * (f1(x) - b) + d (mod p),这表明他们不是很独立。所以你可能会遇到意想不到的问题。