堆栈类对象是否有可推送/可弹出的哈希函数?

时间:2018-04-24 02:15:13

标签: algorithm hash

我知道滚动哈希函数类似于有界队列上的哈希。堆栈有什么类似的东西吗?

我的用例是我正在深入搜索可能的程序跟踪(循环展开,因此这些堆栈可以获得biiiiig),我需要通过这些跟踪来识别分支。而不是存储一堆深度为1000的堆栈,我想要哈希它们,以便我可以通过int索引。但是,如果我有10000+深度的堆栈,这个散列将是昂贵的,所以我想跟踪我的最后一个散列,以便当我从我的堆栈中推/弹时我可以分别散列/取消散列新/旧项目。

特别是,我正在寻找一个带有unhash h(Object, Hash)的散列u(Object, Hash),其中包含要对象x进行哈希处理的属性:

    u(x, h(x, baseHash)) = baseHash

此外,这个哈希不应该是可交换的,因为秩序很重要。

我有一个想法是GL(2, F(2^k))上的矩阵乘法,也许使用Cayley图?例如,在A_0中使用两个可逆矩阵A_1B_0,其中包含反转B_1GL(2, F(2^k)),并计算对象的哈希值{{1首先使用位x计算一些整数哈希,然后计算

b31b30...b1b0

这有一个反向

H(x) = A_b31 . A_b30 . ... . A_b1 . A_b0

因此U(x) = B_b0 . B_b1 . ... . B_b30 . B_31. h(x, baseHash) = H(x) . baseHash,以便

u(x, baseHash) = U(x) . baseHash

根据需要。

这似乎可能比必要的更昂贵,但对于2x2矩阵,它不应该坏?

1 个答案:

答案 0 :(得分:6)

大多数增量散列函数可以通过两种操作来实现:

1)可逆扩散函数,它混合了前一个散列。为此选择了可逆功能,以便它们不会丢失信息。否则哈希会倾向于几个值;和

2)可逆混合函数,用于将新数据混合到散列中。可以使用可逆函数,以便输入的每个部分对最终散列值具有相同的影响。

由于这两件事都是可逆的,因此很容易撤消增量散列的最后一部分和" pop"除了以前的值。

例如,使用的最常见的简单散列函数是多项式散列函数。要使用新输入' x'更新以前的哈希值,您需要计算:

<强> H&#39; = h * A + x mod M

乘法是扩散函数。为了使其可逆, A 必须具有乘法逆mod M - 通常选择 M 为素数,或< strong> M 是 2 的幂, A 是奇数。

因为存在乘法逆,所以只要您仍然可以访问它,就很容易从哈希中弹出最后一个值:

h =(h&#39; - x)*(1 / A)mod M

您可以使用扩展的欧几里德算法查找 A 的倒数:https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm

大多数其他常见的非加密哈希值,如CRC,FNV,murmurHash等,同样易于弹出值。

这些哈希值中的一些在增量工作之后有一个最后的扩散步骤,但该步骤几乎总是可逆的,以确保哈希值可以采用任何值,因此您可以撤消它以返回增量值一部分。

扩散操作通常由原始可逆操作序列组成。要撤消它们,您将以相反的顺序撤消每个操作。您将看到的一些常见类型是:

混合操作通常为+或XOR。