检查字符串哈希是否包含子字符串哈希

时间:2019-03-18 13:20:59

标签: c# string hash

假设我有大量的文档,无论如何我都会对其进行哈希处理(例如Sha256)并存储其哈希值。有没有一种哈希技术可以让我仅通过查看哈希值来检查string1是否包含在string2中?我想避免加载全文。

要澄清:这与sim / min哈希无关,查找近似重复或Levenshtein距离。我正在寻找一种哈希算法,该算法可以使我仅通过查看哈希值就可以检查子字符串。

例如

var string1 = "bla bla bla cat dog bla bla";
var string2 = "cat dog";
var hash1 = HashAlgo(string1); // <-- magic goes here
var hash2 = HashAlgo(string2);
Assert.IsTrue(string1.Contains(string2));
Assert.IsTrue(hash1.Contains(hash2)); // <--- magic goes here

1 个答案:

答案 0 :(得分:3)

考虑一下,这是没有可能的。

首先,所有SHA256哈希具有完全相同的长度。我的答案基于SHA256,但据我所知,这适用于任何哈希方法。

  • 请考虑一个包含1000个字符的文档,其中已包含SHA256哈希值。其哈希值是64位数字。
  • 请考虑一个100个字符的文档,该文档已进行了SHA256哈希处理。它的哈希长度为64位。本文档的内容恰好是较大文档的第一章。
  • 考虑第二个100个字符的文档,该文档已进行了SHA256哈希处理。它的哈希长度为64位。本文档的内容恰好是较大文档的第二章。

较大文件的哈希表不可能包含两个较小文件的哈希表,因为这只有在所有三个哈希表都相等的情况下才有可能

第二,考虑一下我可以从一个1000个字符的文档中获取多少个100个字符的子字符串。它不仅是10(如1000/100 = 10),而是900。将子字符串表示为索引边界,有很多可能性:

  • 0到100
  • 1到101
  • 2至102
  • ...
  • 897至997
  • 898至998
  • 899至999

共有900个选项。假设您的初始文档没有以任何方式重复自身(因此您不会得到两个相等的子字符串),那么这将导致900个(假定的)唯一哈希。

这900个唯一的哈希不能全部都是初始文件哈希的子字符串。

此外,请考虑我们甚至没有考虑过其他长度的子字符串!假设子字符串的长度可能是999,000个不同的子字符串(当然,其中一些会重复)

这甚至都没有想到原始文档的长度可能超过1000个字符。对于具有 n 个字符的任何文档,您都可以期望找到 n *(n-1)个子字符串(长度在1到n之间),并且主要具有唯一的哈希值。

这种可能值的扩展仅在您达到10 77 (更确切地说是2 256 )的数量级时才达到平稳,因为这是多少个唯一SHA哈希可能存在。
在餐巾纸的背面,应该是一个10 38 字节的文档。达到该文件大小后,所有可能的子字符串(任何长度)都必须包含至少一个重复项。

我认为您可以理解为什么您的建议在数学上根本不可能。

  

我将其保留为旁注,但是superpermutations是一个切线主题,值得一看,以了解这是多么不可能。对于7个唯一字符,如果要包含7个字符的所有可能排列,则需要 5907位数字的超级排列。这是我们发现(最小)超置换的最高N。

     

对于900个唯一散列(=十六进制字符的唯一排列)的最初示例,这些都将包含在“主”散列中,因此,主散列的最小所需长度简直无法计算。但是作为绝对的最小值(证明是不能采用的最小值),您的主哈希必须长963个字符(如果您假设每个单个64个字符的子字符串始终为您提供一个唯一的新哈希)

相关问题