【问题标题】:Hash Function without collision无冲突的哈希函数
【发布时间】:2020-05-14 13:22:05
【问题描述】:

基本上我使用的是 rabin karp 中使用的哈希函数。

Fast implementation of Rolling hash 中的函数相同,但我不是散列一个字符串,而是散列一个整数向量。

const unsigned PRIME_BASE = 257;
const unsigned PRIME_MOD = 1000000007;
unsigned hash(const std::vector< unsigned int >& Line)
{
    unsigned long long ret = 0;
    for (int i = 0; i < Line.size(); i++)
    {
        ret = ret*PRIME_BASE + Line[i];
        ret %= PRIME_MOD;
    }
    return ret;
}

问题是我遇到了很多碰撞。更改素数可以最小化或最大化碰撞,但我无法避免。

任何想法如何避免与此类或更好的功能发生冲突?

【问题讨论】:

  • 不可能避免与哈希的冲突。如果你没有冲突,那么你就没有散列函数。
  • 目标是尽量减少冲突,而不是消除它们。除非您有比可能输入更多的可能哈希,否则您将始终存在争用,这在某种程度上违背了哈希的意义。
  • how to avoid collisions 这是不可能的,您可以最大限度地减少特定数据集的冲突,但是对于另一个数据集,相同的哈希函数可能会失败
  • 注意:在 C++ 中将其表示为 std::vector&lt;x&gt; 而不是 std::vector&lt; x &gt; 并带有额外的间距。这最终看起来很奇怪,例如 shell 重定向 (&gt;&amp;) 或小于运算符。
  • 你测量了平均碰撞率吗?

标签: c++ hash


【解决方案1】:

你没有。

哈希的全部意义在于从大域中获取输入,并在较小域中产生输出。

就过程的本质而言,碰撞是不可避免和不可避免的。

您可以try to reduce their likelihood,针对某些特定类别的数据集,但您已经探索过这样做。

【讨论】:

【解决方案2】:

您可以做得更好(减少冲突的机会)以添加更多哈希函数。例如: 创建 2 个哈希函数,具有不同的 PRIME BASE 和 PRIME MOD,并存储一对 long long。

另一个问题可能是 Line 存储了许多零,因此最好向值添加一些随机(在初始化后固定)移位。 例如,如果你想计算 'A' 和 'AA' 散列,最好使用 Robin-Karb {return c-'A';}

另一个有趣的话题我认为如果你选择一个好的哈希函数(从随机方面),并且你的输入也是随机的,那么当 Line 向量中不同项目的数量小于 sqrt(range散列函数),这就是生日悖论。您当前的范围是 1e9+7,所以它的 sqrt 大约是 3e4。如果您使用 2 个哈希函数,则组合范围是它们范围的乘积。

【讨论】:

  • 当然我不想说这个技术是帮你避免碰撞的,我只是说如何在c++中一点点减少碰撞的机会。我建议竞争性编程比赛使用这种技术来避免您的代码被黑客入侵。更多相关信息:codeforces.com/blog/entry/60442,关于多重哈希的最后一节。
  • 是的,但在顶部我看到一个 c++ 代码和一个问题:“有什么想法可以避免与此类函数或更好的函数发生冲突吗?”也许我误会了,我以为他/她正在寻找 smg 以减少碰撞的机会。对此感到抱歉。
  • 被黑的意思是,当我们有一个解决方案时,例如使用 Rabin Karp,当然它可能会失败一些输入。因此,如果其他参与者可以在我们的解决方案失败的情况下找到/生成这样的输入,它会在竞争性编程中调用“被黑”或“被挑战”
  • 可能在这里解释得更好:codeforces.com/blog/entry/1336 第 3 点。
  • @JesperJuhl OP 要求更好的散列函数。正如你自己提到的,唯一的机会就是增加输出空间
猜你喜欢
  • 2019-03-25
  • 2019-03-17
  • 1970-01-01
  • 2014-10-02
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多