二维Hash的板子题,我们先对每行的前缀维护一下Hash值,最对每列维护每行前缀的前缀值
void get_hash(int n,int m,int type)
{
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
if (type) hashs[i][j]=hashs[i][j-1]*base1+s[i][j];
else sub_hash[i][j]=sub_hash[i][j-1]*base1+s[i][j];
for (int j=1; j<=m; j++)
for (int i=1; i<=n; i++)
if (type) hashs[i][j]=hashs[i-1][j]*base2+hashs[i][j];
else sub_hash[i][j]=sub_hash[i-1][j]*base2+sub_hash[i][j];
}
为什么可以分别计算行和列的前缀和?
-
行哈希计算:首先,对于每一行,我们计算从第一个字符到当前字符的前缀和(使用
base1
作为基数)。这相当于将每一行看作一个独立的字符串,并计算其哈希值。这样,hashs[i][j]
就存储了从第i
行第1
个字符到第i
行第j
个字符的哈希值。 -
列哈希计算:接着,我们利用已经计算好的行哈希值,进一步计算跨越多行的列哈希值。对于每一列,我们将每一行的哈希值作为新的“字符”,并使用
base2
作为基数来计算列的前缀和。这样,hashs[i][j]
就存储了从第1
行第j
个字符到第i
行第j
个字符的哈希值(跨越了所有行)。
为什么直接通过矩阵的前缀和计算得到的答案是有问题的?
如果我们尝试直接计算整个矩阵的前缀和来作