与本文有关的问题: https://threads-iiith.quora.com/String-Hashing-for-competitive-programming
作者介绍了这种哈希字符串算法:
其中S是我们的字符串,Si是索引i处的字符,p是我们选择的素数。
然后,他提出了确定给定字符串的子字符串是否为回文的问题,并声称可以通过散列在对数时间内完成。他指出我们可以从整个字符串的开头到子字符串的右边缘计算:
并观察到如果我们计算从子串的开始到左边缘的散列(F(L-1)),这与我们的右边缘的哈希之间的差异基本上是我们子串的哈希: / p>
这一切都很好,我想我到目前为止都遵循它。但他随后立即声称这允许我们在对数时间内计算我们的哈希值(从而通过比较这个哈希与通过以相反顺序移动我们的子串产生的哈希值来确定我们的子串是一个回文)。
我觉得我可能遗漏了一些显而易见的东西,但这又如何让我们以对数时间计算哈希?
答案 0 :(得分:2)
您已经知道可以在恒定时间内计算差异。让我重申一下差异(为了清楚起见,我将模数留下):
diff = ∑_{i=L to R} S_i ∗ p^i
请注意,这不是子字符串的哈希值,因为p
的幂会被常量偏移。相反,这是(如文章所述)
diff = Hash(S[L,R])∗p^L
要派生子字符串的哈希值,必须将差值乘以p^-L
。假设您已经知道p^-1
(这可以在预处理步骤中完成),您需要计算(p^-1)^L
。使用square-and-multiply方法,这需要O(log L)
个操作,这可能是作者所指的。
如果您的查询按L
排序,则效率可能会提高。在这种情况下,您可以逐步计算p^-L
。