对于O(n)的时间/空间复杂度,诀窍是评估每个子序列的哈希值。考虑数组b
:
[b1 b2 b3 ... bn]
使用Horner的方法,您可以评估每个子序列的所有可能哈希值。选择一个基值B
(大于两个数组中的任何值):
from b1 to b1 = b1 * B^1
from b1 to b2 = b1 * B^1 + b2 * B^2
from b1 to b3 = b1 * B^1 + b2 * B^2 + b3 * B^3
...
from b1 to bn = b1 * B^1 + b2 * B^2 + b3 * B^3 + ... + bn * B^n
请注意,您可以使用前一个序列的结果来评估O(1)时间中的每个序列,因此所有作业成本为O(n)。
现在您有了一个数组Hb = [h(b1), h(b2), ... , h(bn)]
,Hb[i]
从b1
到的哈希值在哪里bi
。
对数组执行相同的操作a
,但有一点技巧:
from an to an = (an * B^1)
from an-1 to an = (an-1 * B^1) + (an * B^2)
from an-2 to an = (an-2 * B^1) + (an-1 * B^2) + (an * B^3)
...
from a1 to an = (a1 * B^1) + (a2 * B^2) + (a3 * B^3) + ... + (an * B^n)
必须注意的是,当您从一个序列移至另一个序列时,请将整个先前序列乘以B,然后将新值乘以B。例如:
from an to an = (an * B^1)
for the next sequence, multiply the previous by B: (an * B^1) * B = (an * B^2)
now sum with the new value multiplied by B: (an-1 * B^1) + (an * B^2)
hence:
from an-1 to an = (an-1 * B^1) + (an * B^2)
现在您有了一个数组Ha = [h(an), h(an-1), ... , h(a1)]
,Ha[i]
从ai
到的哈希值在哪里an
。
现在,您可以比较从n到1的Ha[d] == Hb[d]
所有d
值,如果它们匹配,您将得到答案。
注意:这是一个哈希方法,值可能很大,您可能必须使用快速取幂方法和模块化算术,这可能(几乎)给您带来冲突,从而使此方法并不完全安全。一个好的做法是选择一个底数B
作为一个非常大的素数(至少大于数组中的最大值)。您还应该小心,因为数字的限制可能会在每个步骤中溢出,因此您必须K
在每个操作中使用(取模)(其中K
可能比素数大B
)。
这意味着两个不同的序列可能具有相同的哈希,但是两个相等的序列将始终具有相同的哈希。
b[1] to b[d]
,然后转到数组a
计算哈希值(a[1] to a[d]
如果匹配),这就是您的答案;如果不计算哈希值,则可以a[2] to a[d+1]
通过重新使用为计算得出的哈希值a[1] to a[d]
。但是我不知道数组中的对象是否适合在其上计算滚动哈希。