检测随机有序输入中的更改(哈希函数?)

时间:2020-03-05 18:53:49  来源:igfitidea点击:

我正在阅读可以任意顺序排列的文本行。问题在于输出实际上可以与先前的输出相同。我如何才能检测到这种情况,而无需先对输出进行排序?

是否存在某种哈希函数可以接受相同的输入,但是以任何顺序输入,并且仍会产生相同的结果?

解决方案

回答

所以你输入像

A B C D
D E F G
C B A D

并且我们需要检测第一行和第三行是否相同?

回答

如果要确定两个文件是否包含相同的行集,但顺序不同,可以在每行上单独使用常规哈希函数,然后将它们与顺序无关紧要的函数(例如加法)组合在一起。

回答

如果行相当长,则可以保留每行的哈希列表-对其进行排序并与以前的输出进行比较。

如果不需要100%防呆解决方案,则可以将每行的哈希存储在Bloom过滤器中(在Wikipedia上查找),并在处理结束时比较Bloom过滤器。这可能会给我们带来误报(即我们认为我们具有相同的输出,但实际上并不相同),但是我们可以通过调整Bloom过滤器的大小来调整错误率...

回答

如果将每个字符的ASCII值相加,则无论顺序如何,都会得到相同的结果。

(这可能有点简化,但也许会激发我们一个主意。
有关有趣的背景故事,请参见《编程珍珠》第2.8节。)

回答

最简单的方法似乎是散列途中的每一行,存储散列和原始数据,然后将每个新散列与现有散列的集合进行比较。如果得到肯定的结果,则可以比较实际数据,以确保它不是假阳性,尽管这种情况极为罕见,我们可以使用更快的哈希算法,例如MD5或者CRC(而不是SHA等,速度较慢,但​​发生碰撞的可能性较小),只是速度很快,然后在我们遇到问题时比较实际数据。

回答

任何基于散列的方法都可能产生不好的结果,因为一个以上的字符串可以产生相同的散列。 (这不太可能,但是有可能。)添加散列的建议尤其如此,因为从本质上讲,我们将对散列值进行特别糟糕的散列。

仅当对遗漏更改或者发现不存在更改的情况并不重要时,才应尝试使用哈希方法。

最准确的方法是使用线串作为键保留Map,并将每个计数存储为值。 (如果每个字符串只能出现一次,则不需要计数。)为预期的行集计算此值。复制此集合以检查传入的行,从而减少看到的每行的计数。

  • 如果遇到计数为零的行(或者根本没有映射条目),那么我们会看到未曾想到的行。
  • 如果我们以在地图中剩余的非零条目结束此操作,那么我们将看不到预期的内容。

回答

好了,问题说明有点受限制。

据我了解,我们希望查看几个字符串是否包含相同的元素,而不管顺序如何。

例如:

A B C
C B A

是相同的。

这样做的方法是创建一组值,然后比较这些组。要创建集合,请执行以下操作:

HashSet set = new HashSet();
foreach (item : string) {
   set.add(item);
}

然后,只需遍历其中一个集合并与其他集合进行比较,就可以比较集合的内容。对于排序示例,执行时间将是O(N)而不是O(NlogN)。