【问题标题】:Is there a pushable/poppable hash function for stack-like objects?对于类似堆栈的对象,是否有可推送/可弹出的哈希函数?
【发布时间】:2018-04-24 11:18:29
【问题描述】:

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

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

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

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

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

我的一个想法是GL(2, F(2^k)) 上的矩阵乘法,也许使用凯莱图?例如,在GL(2, F(2^k)) 中取两个可逆矩阵A_0A_1,以及逆矩阵B_0B_1,并通过首先计算一些带有位@987654332 的整数散列来计算对象x 的散列@,然后计算

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) . baseHashu(x, baseHash) = U(x) . baseHash,这样

u(x, h(x, base)) = U(x) . H(x) . base = base,

根据需要。

这看起来可能比必要的要贵,但对于 2x2 矩阵,它应该不会糟糕吗?

【问题讨论】:

    标签: algorithm hash


    【解决方案1】:

    大多数增量哈希函数可以由两种操作组成:

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

    2) 将新数据混合到哈希中的可逆混合函数。为此使用了可逆函数,以便输入的每一部分对最终的哈希值具有相同的影响。

    因为这两个东西都是可逆的,所以很容易撤消增量散列的最后一部分并“弹出”前一个值。

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

    h' = h*A + x mod M

    乘法是扩散函数。为了使其可逆,A 必须有一个乘法逆模 M——通常要么选择 M 作为素数,要么选择 M strong>M 是 2 的幂,A 是奇数。

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

    h = (h' - x)*(1/A) mod M

    您可以使用扩展欧几里得算法求A的逆:https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm

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

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

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

    混合操作通常是 + 或 XOR。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-07
      • 2017-12-29
      • 2019-06-29
      • 2016-07-21
      • 2012-07-22
      • 1970-01-01
      • 2012-10-24
      • 2023-03-25
      相关资源
      最近更新 更多