字符串哈希

字符串哈希

可以快速判断字符串是否相同(比KMP还快)

字符串前缀哈希法

先预处理出来所有前缀的哈希

str = "ABCDEFGHI";
h[0] = 0;
h[1] = "A"; // 哈希值
h[2] = "AB";
h[3] = "ABC";
h[4] = "ABCD";
...

求字符串哈希值的方法是将字符串看成一个p进制的数:

"ABCD"
第一位的数是:A - 1
第二位的数是:B - 2
第三位的数是:C - 3
第四位的数是:D - 4

则p进制数对应的十进制数为$(1\ 2\ 3\ 4)_p = (1\times p^3 + 2\times p^2 + 3\times p^1 + 4\times p^0)\mod{q} $

因为字符串可能很长,导致数字很大,所以最后要mod上一个比较小的数字q,映射到\(0\sim q-1\)

注:

  1. 第一步字符映射中不能映射成0,如\(A_p - 0\),则\(AA_p - 0\)
  2. 该方法不考虑冲突情况

经验:p = 131 或 13331,q = \(2^{64}\)

由此可以求出任何子段的哈希值:

pPcZ3jO.png

\[\begin{aligned} & h[R]\quad p^R\dots p^0 \\ & h[L-1]\quad p^{L-1}\dots p^0 \\ & \text{将其对齐:} \\ & h[R]\quad p^R\dots p^0 \\ & h[L-1]\times p^{R-L+1}\quad p^{R}\dots p^{R-L+1} \\ & \text{故最终公式为:}h[R]-h[L]\times p^{R-L+1} \end{aligned} \]

h数组使用unsigned long long类型,溢出也就相当于取模了

typedef unsigned long long ULL;
const int N = 100010, P = 131;
char str[N];
ULL h[N], p[N];
// p数组预处理P的多少次方
// h数组为个长度子串哈希

ULL get(int l, int r) { // 获取任意子串的哈希值
	return h[r] - h[l - 1] * p[r - l + 1];
}

p[0] = 1;
for (int i = 1; i <= n; i++) {
	p[i] = p[i - 1] * P;
	h[i] = h[i - 1] * P + str[i];
}
posted @ 2023-09-09 20:33  -37-  阅读(30)  评论(0编辑  收藏  举报