Хеширование строк: различия между версиями

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
 
(не показано 12 промежуточных версий этого же участника)
Строка 1: Строка 1:
  unsigned long long X = 31, p[100010], h[100010];
h<sub>i</sub> = s<sub>0</sub>x<sup>n - 1</sup> + s<sub>1</sub>x<sup>n - 2</sup> + ... + s<sub>n - 2</sub>x + s<sub>n - 1</sub>.
 
struct Hasher {
    long long mod;
    vector<long long> p, h;
   
    Hasher(const string &s, long long factor = 31, long long mod = 1e9 + 7) : mod(mod) {
        p.push_back(1);
        for (int i = 1; i < s.size(); i++)
            p.push_back(p[i - 1] * factor % mod);
        h.push_back(s[0] - 'a' + 1);
        for (int i = 1; i < s.size(); i++)
            h.push_back((h[i - 1] * factor % mod + s[i] - 'a' + 1) % mod);
    }
    long long getHash(int l, int r) {
        long long res = h[r];
        if (l)
            res = (res - p[r - l + 1] * h[l - 1] % mod + mod) % mod;
        return res;
    }
};
 
struct DoubleHasher {
    Hasher h1, h2;
    DoubleHasher(const string &s) : h1(s), h2(s, 29, 1e9 + 9) {}
    pair<long long, long long> getHash(int l, int r) {
        return { h1.getHash(l, r), h2.getHash(l, r) };
    }
};
 
struct Hasher2D {
    long long mod;
    vector<long long> py, px;
    vector<vector<long long>> h;
    Hasher2D(const vector<string> &a, long long factorY = 29, long long factorX = 31, long long mod = 1e9 + 7) : mod(mod) {
        py.push_back(1);
        for (int y = 1; y < a.size(); y++)
            py.push_back(py[y - 1] * factorY % mod);
        px.push_back(1);
        for (int x = 1; x < a[0].size(); x++)
            px.push_back(px[x - 1] * factorX % mod);
   
   
void buildHash(char *s) {
        h.assign(a.size(), vector<long long>(a[0].size()));
    p[0] = 1;
        for (int y = 0; y < a.size(); y++) {
    h[0] = s[0] - 'a';
            for (int x = 0; x < a[0].size(); x++) {
    for (int i = 1; s[i]; i++) {
                h[y][x] = (a[y][x] - 'a' + 1) % mod;
        p[i] = p[i - 1] * X;
                if (y)
        h[i] = h[i - 1] + p[i] * (s[i] - 'a');
                    h[y][x] = (h[y][x] + h[y - 1][x] * factorY) % mod;
                if (x)
                    h[y][x] = (h[y][x] + h[y][x - 1] * factorX) % mod;
                if (y && x)
                    h[y][x] = ((h[y][x] - h[y - 1][x - 1] * factorY * factorX) % mod + mod) % mod;
            }
        }
     }
     }
}
   
   
bool areEqual(int l1, int r1, int l2, int r2) {
    long long getHash(int yl, int xl, int yr, int xr) {
    unsigned long long h1 = h[r1] - (l1 ? h[l1 - 1] : 0);
        long long res = h[yr][xr];
    unsigned long long h2 = h[r2] - (l2 ? h[l2 - 1] : 0);
        if (yl)
    if (l1 < l2)
            res = (res - py[yr - yl + 1] * h[yl - 1][xr] % mod + mod) % mod;
        h1 *= p[l2 - l1];
        if (xl)
    if (l2 < l1)
            res = (res - px[xr - xl + 1] * h[yr][xl - 1] % mod + mod) % mod;
        h2 *= p[l1 - l2];
        if (yl && xl)
    return h1 == h2;
            res = (res + py[yr - yl + 1] * px[xr - xl + 1] % mod * h[yl - 1][xl - 1]) % mod;
  }
        return res;
    }
  };
 
<!--{| width="100%"
| width=50% |
h<sub>i</sub> = s<sub>0</sub> + s<sub>1</sub>x + s<sub>2</sub>x<sup>2</sup> + ... + s<sub>n - 1</sub>x<sup>n - 1</sup>.
 
Для выравнивания хеши различных подстрок домножаются на x<sup>n - 1 - L</sup>.


  struct Hasher {
  struct Hasher {
     unsigned long long f, mod, p[210], h[210];
     long long x = 31, mod = 1e9 + 7;
     Hasher() {
    vector<long long> p, h;
         f = 31;
         mod = 1e9 + 7;
     Hasher(const string &s) {
         p.resize(s.size());
         h.resize(s.size());
         p[0] = 1;
         p[0] = 1;
         for (int i = 1; i < 210; i++)
        h[0] = s[0] - 'a' + 1;
             p[i] = (p[i - 1] * f) % mod;
         for (int i = 1; i < s.size(); i++) {
             p[i] = p[i - 1] * x % mod;
            h[i] = (h[i - 1] + p[i] * (s[i] - 'a' + 1) % mod) % mod;
        }
    }
    long long getHash(int l, int r) {
        long long res = h[r];
        if (l)
            res = (res - h[l - 1] + mod) % mod;
        res = res * p[p.size() - 1 - l] % mod;
        return res;
     }
     }
     void buildHash(char s[]) {
};
 
Этот способ непригоден для сравнения участков двух строк разной длины. В данном случае хеш более левого участка следует домножать на x<sup>|L1 - L2|</sup>.
| width="10px" | &nbsp;
| width=50% |
h<sub>i</sub> = s<sub>0</sub> + s<sub>1</sub>x + s<sub>2</sub>x<sup>2</sup> + ... + s<sub>n - 1</sub>x<sup>n - 1</sup>.
 
Для выравнивания хеши различных подстрок домножаются на (x<sup>-1</sup>)<sup>L</sup>.
 
struct Hasher {
    long long x = 31, {{Changed|1=xi = 129032259,}} mod = 1e9 + 7;
     vector<long long> p, {{Changed|pi,}} h;
    Hasher(const string &s) {
        p.resize(s.size());
        {{Changed|pi.resize(s.size());}}
        h.resize(s.size());
        p[0] = {{Changed|1=pi[0] = }} 1;
         h[0] = s[0] - 'a' + 1;
         h[0] = s[0] - 'a' + 1;
         for (int i = 1; s[i]; i++)
             h[i] = (h[i - 1] + ((s[i] - 'a' + 1) * p[i]) % mod) % mod;
         for (int i = 1; i < s.size(); i++) {
            p[i] = p[i - 1] * x % mod;
            {{Changed|1=pi[i] = pi[i - 1] * xi % mod;}}
             h[i] = (h[i - 1] + p[i] * (s[i] - 'a' + 1) % mod) % mod;
        }
     }
     }
     unsigned long long getHash(int l, int r) {
         return ((h[r] - (l ? h[l - 1] : 0) + mod) % mod * p[209 - l]) % mod;
     long long getHash(int l, int r) {
         long long res = h[r];
        if (l) {
            res = (res - h[l - 1] + mod) % mod;
            {{Changed|1=res = (res * pi[l]) % mod}};
        }
        return res;
     }
     }
  } hasher;
  };
|}-->


== Ссылки ==
== Ссылки ==
Строка 44: Строка 148:
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8_%D0%B2_%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B5_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D1%85%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F._%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D0%B0%D0%B1%D0%B8%D0%BD%D0%B0-%D0%9A%D0%B0%D1%80%D0%BF%D0%B0 neerc.ifmo.ru &mdash; Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8_%D0%B2_%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B5_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D1%85%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F._%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D0%B0%D0%B1%D0%B8%D0%BD%D0%B0-%D0%9A%D0%B0%D1%80%D0%BF%D0%B0 neerc.ifmo.ru &mdash; Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BD%D0%B0%D0%B8%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%D0%B9_%D0%BE%D0%B1%D1%89%D0%B5%D0%B9_%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8_%D0%B4%D0%B2%D1%83%D1%85_%D1%81%D1%82%D1%80%D0%BE%D0%BA_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D1%85%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F neerc.ifmo.ru &mdash; Поиск наибольшей общей подстроки двух строк с использованием хеширования]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BD%D0%B0%D0%B8%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%D0%B9_%D0%BE%D0%B1%D1%89%D0%B5%D0%B9_%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8_%D0%B4%D0%B2%D1%83%D1%85_%D1%81%D1%82%D1%80%D0%BE%D0%BA_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D1%85%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F neerc.ifmo.ru &mdash; Поиск наибольшей общей подстроки двух строк с использованием хеширования]
* [https://ru.algorithmica.org/cs/hashing/polynomial/ ru.algorithmica.org — Полиномиальное хеширование]
* [http://habrahabr.ru/post/142589/ habrahabr.ru &mdash; Полиномиальные хеши и их применение]
* [http://habrahabr.ru/post/142589/ habrahabr.ru &mdash; Полиномиальные хеши и их применение]
* [http://codeforces.com/blog/entry/4898 codeforces.com &mdash; Anti-hash test]
* [http://codeforces.com/blog/entry/4898 codeforces.com &mdash; Anti-hash test]
* [http://codeforces.com/blog/entry/60445 codeforces.com — Полиномиальное хеширование + разбор интересных задач]
* [https://blog.algoprog.ru/hash-no-multiply/ Калинин П. — Про хеширование без домножения]
* [https://usaco.guide/gold/string-hashing?lang=cpp usaco.guide — String Hashing]
Код:
Код:
* [http://github.com/indy256/codelibrary/blob/master/java/src/Hashing.java CodeLibrary &mdash; Hashing on strings]
* [https://github.com/indy256/codelibrary/blob/master/cpp/strings/hashing.cpp codelibrary/cpp/strings/hashing.cpp]
* [http://github.com/ADJA/algos/blob/master/Strings/Hashing.cpp Algos &mdash; Hashing in strings based problems]
* [https://github.com/ADJA/algos/blob/master/Strings/Hashing.cpp algos/Strings/Hashing.cpp]
Задачи:
Задачи:
* [[:Категория: Задачи: Хеширование строк|Задачи: Хеширование строк]]
* [[:Категория: Задачи: Хеширование строк|Задачи: Хеширование строк]]


[[Категория:Строки]]
[[Категория:Строки]]

Текущая версия от 01:48, 18 декабря 2025

hi = s0xn - 1 + s1xn - 2 + ... + sn - 2x + sn - 1.

struct Hasher {
    long long mod;
    vector<long long> p, h;

    Hasher(const string &s, long long factor = 31, long long mod = 1e9 + 7) : mod(mod) {
        p.push_back(1);
        for (int i = 1; i < s.size(); i++)
            p.push_back(p[i - 1] * factor % mod);

        h.push_back(s[0] - 'a' + 1);
        for (int i = 1; i < s.size(); i++)
            h.push_back((h[i - 1] * factor % mod + s[i] - 'a' + 1) % mod);
    }

    long long getHash(int l, int r) {
        long long res = h[r];
        if (l)
            res = (res - p[r - l + 1] * h[l - 1] % mod + mod) % mod;
        return res;
    }
};
struct DoubleHasher { 
    Hasher h1, h2;

    DoubleHasher(const string &s) : h1(s), h2(s, 29, 1e9 + 9) {}

    pair<long long, long long> getHash(int l, int r) {
        return { h1.getHash(l, r), h2.getHash(l, r) };
    }
};
struct Hasher2D {
    long long mod;
    vector<long long> py, px;
    vector<vector<long long>> h;

    Hasher2D(const vector<string> &a, long long factorY = 29, long long factorX = 31, long long mod = 1e9 + 7) : mod(mod) {
        py.push_back(1);
        for (int y = 1; y < a.size(); y++)
            py.push_back(py[y - 1] * factorY % mod);

        px.push_back(1);
        for (int x = 1; x < a[0].size(); x++)
            px.push_back(px[x - 1] * factorX % mod);

        h.assign(a.size(), vector<long long>(a[0].size()));
        for (int y = 0; y < a.size(); y++) {
            for (int x = 0; x < a[0].size(); x++) {
                h[y][x] = (a[y][x] - 'a' + 1) % mod;
                if (y)
                    h[y][x] = (h[y][x] + h[y - 1][x] * factorY) % mod;
                if (x)
                    h[y][x] = (h[y][x] + h[y][x - 1] * factorX) % mod;
                if (y && x)
                    h[y][x] = ((h[y][x] - h[y - 1][x - 1] * factorY * factorX) % mod + mod) % mod;
            }
        }
    }

    long long getHash(int yl, int xl, int yr, int xr) {
        long long res = h[yr][xr];
        if (yl)
            res = (res - py[yr - yl + 1] * h[yl - 1][xr] % mod + mod) % mod;
        if (xl)
            res = (res - px[xr - xl + 1] * h[yr][xl - 1] % mod + mod) % mod;
        if (yl && xl)
            res = (res + py[yr - yl + 1] * px[xr - xl + 1] % mod * h[yl - 1][xl - 1]) % mod;
        return res;
    }
};


Ссылки

Теория:

Код:

Задачи: