在我的程序中,我有一组存储在专有哈希表中的集合。像所有哈希表一样,我需要为每个元素使用两个函数。首先,我需要用于插入的哈希值。其次,在发生冲突时我需要一个比较功能。在我看来,校验和功能对此非常完美。我可以在两个函数中使用该值。校验和功能并不缺,但我想知道是否有任何我不需要带入库中的常用功能(我的公司是PIA,当涉及到那个。系统库没问题。
但我有一个额外的,更复杂的要求。我需要逐步计算校验和。也就是说,如果一个集合包含A B C D E F并且我从集合中减去D,它应该能够返回一个新的校验和值,而不会再次迭代集合中的所有元素。这样做的原因是为了防止我的代码出现非线性。理想情况下,我希望校验和与顺序无关,但如果需要,我可以先对它们进行排序。这样的算法是否存在?
答案 0 :(得分:1)
只需在您的集合中存储项目字典及其对应的哈希值。集合的哈希值是项目的连接的,排序的哈希值的哈希值。在Python中:
hashes = '''dictionary of hashes in string representation'''
# e.g.
hashes = { item: hashlib.sha384(item) for item in items }
sorted_hashes = sorted(hashes.values())
concatenated_hashes = ''.join(sorted_hashes)
hash_of_the_set = hashlib.sha384(concatenated_hashes)
作为哈希函数,我会使用sha384,但您可能想尝试使用Keccak-384。
因为(当然)没有长度仅为32位的加密散列函数,所以必须使用校验和,如Adler-32或CRC32。这个想法保持不变。最好在项目上使用Adler32,在连接的哈希上使用crc32:
hashes = { item: zlib.adler32(item) for item in items }
sorted_hashes = sorted(hashes.values())
concatenated_hashes = ''.join(sorted_hashes)
hash_of_the_set = zlib.crc32(concatenated_hashes)
答案 1 :(得分:1)
CRC是从输入计算的一组位。
如果您的输入与CRC(在您的情况下为32位)的大小(或更小)相同,您可以找到创建此CRC的输入 - 实际上是将其反转。
如果您的输入大于32位,但除了32位以外您知道所有输入,您仍然可以反转CRC以找到丢失的位。
但是,如果输入的未知部分大于32位,则无法找到它,因为有多个解决方案。
为什么我这样告诉你?想象一下,你有集合的CRC
{A,B,C}
假设您知道B
是什么,现在您可以轻松计算集合的CRC
{A,C}
(“很容易”我的意思是 - 没有超过整个A
和C
输入 - 就像你想要的那样)
现在您有64位描述A
和C
!由于我们没有必要完成A
和C
的全部操作 - 这意味着即使我们缺少有关A
和{{的信息,我们也可以这样做1}}。
所以看起来如果这样的方法存在,如果我们有CRC的话,我们可以从输入中神奇地修复超过32个未知位。
这显然是错误的。这是否意味着没有办法做你想做的事情?当然不是。但它确实限制了我们如何做到这一点:
选项1:我们无法从C
中获取CRC({A,C})
中没有的更多信息。这意味着CRC({A,B,C})
和A
对CRC的(相对)影响不会随着C
的移除而改变。基本上 - 这意味着在计算CRC时,我们在添加新元素时会使用一些“order not important”函数:
我们可以使用,例如B
(不是很好,好像A出现两次,它是相同的CRC,就好像它根本没有出现过),或CRC({A,B,C}) = CRC(A) ^ CRC(B) ^ CRC(C)
或CRC({A,B,C}) = CRC(A) + CRC(B) + CRC(C)
(确保CRC({A,B,C}) = CRC(A) * CRC(B) * CRC(C)
是奇数,所以它实际上只是31位CRC)或CRC(X)
(其中CRC({A,B,C}) = g^CRC(A) * g^CRC(B) * g^CRC(C)
是强大的 - 如果你想要加密安全的话很有用)等。
选项2:我们确实需要^
和A
全部来计算C
,但我们有一个数据结构,使其低于线性如果我们已经计算了CRC({A,C})
,那么还有时间。
如果您需要专门的CRC32,这很有用,并且在计算之后不介意记住CRC之外的更多信息(CRC仍然是32位,但是你记得数据结构是O(len(A,B) ,C))您稍后将用于更有效地计算CRC {A,C})
这将如何运作?许多CRC只是在输入上应用多项式。
基本上,如果您将输入分为CRC({A,B,C})
每个32位的块 - n
- 有一个矩阵X_1...X_n
,那么
M
(这里CRC(X_1...X_n) = M^n * X_1 + ... + M^1 * X_n
就是权力)
这有什么帮助?这个总和可以用树状计算:
^
所以你从树的叶子上的所有CRC(X_1...X_n) = M^(n/2) * CRC(X_1...X_n/2) + CRC(X_(n/2+1)...X_n)
开始,首先计算每个连续对的CRC,然后成对组合它们,直到得到你所有输入的组合CRC。
如果您记住节点上的所有部分CRC,则可以通过X_i
计算轻松删除(或添加)列表中任何位置的项目!
所以 - 据我所知,这是你的两个选择。我希望这不是一个烂摊子:)
我个人选择选项1,因为它更简单......但是得到的CRC不是标准的,而且不太好......。不像“CRC”那样。
干杯!