参考字符串哈希中多项式 $Hash $函数定义:

$f(s) = \sum_{i=1}^{l} s[i] \times b^{l-i} \pmod M$
及其推论:

$f(s[l..r])=f_r(s)-f_{l-1}(s) \times b^{r-l+1}$

我们可以写出$Hash$的实现:

const LL M = 33951943;
const LL BA = 233;
    hash_at[1] = (sum[1] - sum[0]) % 3;
    for (int k = 2; k <= sum_0; k++)
    {
        hash_at[k] = ((sum[k] - sum[k - 1]) % 3 + hash_at[k - 1] * BA) % M;
    }

其中 hash_at[] 储存hash值
而又由推论,我们可以简易地借助快速幂来得到$[l,r]$的hash值

LL quikpower(LL b)
{
    LL ans = 1, base = BA;
    while (b > 0)
    {
        if (b & 1)
        {
            ans *= base;
            ans %= M;
        }
        base *= base;
        base %= M;
        b >>= 1;
    }
    return ans;
}
LL gethash(int l, int r)
{
    if (l == 1)
        return hash_at[r];
    return (hash_at[r] + M - hash_at[l- 1]] * quikpower(r- l+ 1) % M) % M;
    //加M防止hash值为负数
}

由于unsigned long long的特性,我们有自然溢出的做法:

#define LL long long
const LL B = 13331;
typedef unsigned long long ull;
ull hashs[200087], po[200087];/*hashs储存hash值,po数组储存B的n次方*/
void hash_init()
{
    int sum_0 = n - sum[n];
    po[0] = 1;
    po[1] = B;
    hashs[bk[1]] = (sum[bk[1]] - sum[0]) % 3; 
    for (int k = 2; k <= sum_0; k++)
    {
        hashs[k] = ((sum[k] - sum[k - 1]) % 3 + hashs[k - 1] * B);
        po[k] = po[k - 1] * B;
    }
}
LL gethash(int l, int r)
{
    if (l == 1)
        return hashs[r];
    return (hashs[r] - hashs[l- 1] * po[r - l+ 1]);
}
此文章已被阅读次数:正在加载...更新于