【问题标题】:Comparing long strings by their hashes通过哈希值比较长字符串
【发布时间】:2012-05-10 13:23:16
【问题描述】:

为了提高比较字符串的函数的性能,我决定通过比较它们的哈希值来比较它们。 那么是否可以保证如果 2 个非常长的字符串的哈希值彼此相等,那么这些字符串也彼此相等?

【问题讨论】:

  • 我相信是的。哈希是它们包含的数据的绝对表示。所以相等的字符串应该有相等的哈希值。
  • 为什么不首先比较字符串。计算哈希将迫使您检查两个字符串的每个字符。比较它们也是如此(但这可能会在第一次不匹配时返回“不相等”)
  • @Jeremy1026:这根本不是真的。假设您使用 4 位散列。 4 位可以容纳 2^4 = 16 个不同的值,因此您永远无法区分超过 16 个具有该哈希的字符串。在实践中,散列通常是数百位,但它们可以区分的项目数量总是有限的。当然,对于足够长的散列,冲突是极不可能发生的,但不能保证不同的字符串会有不同的散列。

标签: string hash compare


【解决方案1】:

虽然可以保证 2 个相同的字符串会为您提供相同的哈希值,但反之则不然:对于给定的哈希值,总会有几个可能的字符串产生相同的哈希值。 由于PigeonHole principle,这是正确的。

话虽如此,两个不同的字符串产生相同哈希的机会可以变得非常小,以至于被认为等于 null。

这种散列的一个相当经典的例子是MD5,它具有近乎完美的 128 位分布。这意味着您在 2^128 中有一次机会 2 个不同的字符串产生相同的哈希。嗯,基本上,几乎和不可能一样。

【讨论】:

  • 有趣的是,MD5 已被破坏:攻击者可以有意创建一个散列到任何给定值的字符串。根本就没有足够的比特,这就是为什么 SHA 已成为当前密码学标准的原因。
  • 是的,这是“随机碰撞”和“故意碰撞”之间的巨大差异。在随机方面,MD5 仍然足够好。现在,如果系统必须考虑故意碰撞的风险(这并不总是必要的),那么是的,MD5 已经不够好了。
  • 生成和比较 MD5 哈希值如何比比较原始字符串更快?!?
  • 可能不会更快。实际上,这取决于用例。通常,如果只进行一次比较,那么直接比较原始字符串会更快。但是,如果必须多次比较它,通常是寻找重复项,或者如果必须存储结果以供以后重复使用,那么比较哈希会占上风。
【解决方案2】:

在比较两个长字符串以确定它们是否相同的简单常见情况下,出于两个原因,简单比较比散列更可取。首先,正如@wildplasser 所指出的,哈希要求必须遍历两个字符串的所有字节才能计算两个哈希值,而简单比较速度很快,只需要遍历字节直到找到第一个差异,这可能远小于完整的字符串长度。其次,简单的比较可以保证检测到任何差异,而哈希仅给出它们相同的高概率,正如@AdamLiss 和@Cyan 所指出的那样。

但是,在一些有趣的情况下,可以使用哈希比较来获得极大的优势。正如@Cyan 所提到的,如果要进行多次比较,或者必须存储以供以后使用,那么散列可能会更快。其他人未提及的情况是字符串是否位于通过本地网络或 Internet 连接的不同机器上。在两台机器之间传递少量数据通常会快得多。最简单的第一个检查是比较两者的大小,如果不同,你就完成了。否则,计算散列,每个都在自己的机器上(假设你能够在远程机器上创建进程),如果不同,你就完成了。如果哈希值相同,并且您必须有绝对的确定性,那么就没有简单的捷径可以达到确定性。在两端使用无损压缩将允许传输较少的数据以进行比较。最后,如果这两个字符串按时间分隔,正如@Cyan 所暗示的那样,如果您想知道一个文件自昨天以来是否已更改,并且您已经存储了昨天版本的哈希,那么您可以将今天的哈希与它进行比较.

我希望这将有助于激发一些“开箱即用”的想法。

【讨论】:

    【解决方案3】:

    我不确定你的表现是否会得到改善。两者:构建哈希 + 比较整数和简单地使用 equals 比较字符串具有相同的复杂性,即 O(n),其中 n 是字符数。

    【讨论】:

      猜你喜欢
      • 2011-03-27
      • 2015-03-07
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多