首页 > 技术文章 > 【字符串】字符串多项式哈希

purinliang 2020-11-30 12:54 原文

这个太不好用了

设哈希函数为多项式

\[f(s) = \sum\limits_{i=1}^n x^{n-i}*s[i] \]

这种方法称为字符串多项式哈希,优点是:方便递推、可以方便取出里面的子串。把[1..L-1]的前缀的多项式再乘以x^{R-L+1}次方,和[1..R]的前缀的多项式对应位置对齐,然后作差把前面多余的减掉。

struct Hashcode {

    static const int MAXN = 1e5 + 10;
    static ull MOD[2];
    static ull BASE[2];
    static ull PBASE[MAXN][2];

    int len;
    ull code[2];

    static void init(int n) {
        MOD[0] = 998244353, MOD[1] = 1004535809;
        BASE[0] = 163, BASE[1] = 233;
        PBASE[0][0] = 1, PBASE[0][1] = 1;
        for (int i = 1; i <= n; ++i) {
            PBASE[i][0] = PBASE[i - 1][0] * BASE[0] % MOD[0];
            PBASE[i][1] = PBASE[i - 1][1] * BASE[1] % MOD[1];
        }
    }

    static Hashcode concat(const Hashcode &x, const Hashcode &y) {
        Hashcode res;
        res.len = x.len + y.len;
        res.code[0] = (x.code[0] * PBASE[y.len][0] + y.code[0]) % MOD[0];
        res.code[1] = (x.code[1] * PBASE[y.len][1] + y.code[1]) % MOD[1];
        return res;
    }

    ull getHashcode() {
        return (code[0] << 32) | code[1];
    }

};

假如要截取字符串的子串,则是要把对应R位置的[1,R]的多项式减去[1,L-1]的多项式乘以x^(R-L+1)次方。

推荐阅读