哈希

哈希

概述

  • 哈希最优秀的点,或者是用哈希的目的就是比较两个东西做到O(1)的复杂度

  • 这个东西可能是:字符串,数列,甚至是树,图,你能想到的东西都可以根据不同哈希函数映射成数字,只不过难度有所不同

  • 此篇文章特别介绍用的比较多的哈希方法:字符串哈希,数列哈希,树哈希

  • 也引出三种常用哈希方式:进制哈希,异或哈希,西格玛换根哈希

哈希方式:

进制哈希:

  • 最简单的例子1,0,1,1,0 这个数列你可以想象成二进制那么就可以用二进制转换为十进制数,用一个十进制的22表示整个数列,推广到m进制数都是一样的;

代码实现:

for(int i = 1;i <= n;i++){
	hs[i] = hs[i - 1] * m + a[i];
}

异或哈希:

mt19937_64 rnd(time(0));
for(int i = 1;i <= m;i++){
    v[i] = rnd();
}
for(int i = 1;i <= n;i++){
    hs[i] = hs[i-1]^v[a[i]];
}

放大值域映射,不用质疑正确性,在极大范围内的映射,出现错误的概率极小

  • 比如说 4的范围内 2+3 = 5, 1 + 2 = 5, 容易碰撞,碰撞概率为 2/10,放到1e18的值域下呢,其碰撞概率可能比天上掉馅饼概率还低

**这样映射有什么好处? **

  1. 异或性质 a ^ a = 0;
  2. 可以判断元素在字段中出现次数的奇偶性
  3. hs[l,r] = hs[r] ^ hs[l - 1]

字符串哈希

每个字符的ACSII码,转换成数,利用进制哈希法

哈希过程:

字符串的进制,我们下面简称为Base

  1. 我们通常选用 13331,131,根据一些复杂的讨论,实际上单哈希开的越大越好13331比131好,并且可以使用__int128,这样极大降低被卡风险,当然也可用双哈希,三哈希降低

  2. 通常需要取模,或者ULL自然溢出

  3. 如何求一个子串的哈希值:

    hs[r] - hs[l - 1]*p[r - l + 1]
    

课上例题:

1.P3501 [POI2010] ANT-Antisymmetry :

https://www.luogu.com.cn/problem/P3501

(字符串哈希+二分枚举分割线判断异或回文串)

题解:https://www.luogu.com.cn/record/195514227

2.F - Palindrome Query:

https://atcoder.jp/contests/abc331/tasks/abc331_f

(线段树维护字符串哈希)

题解:https://atcoder.jp/contests/abc331/submissions/61020931

小结:

与其说字符串哈希是一种算法,不如说其是一种思想,往往题目不会单考字符串哈希,而是和其他算法结合来考;

字符串哈希是不会字符串算法同学们的福利,往往Kmp,ac自动机,后缀数组等高难度算法解的题目,用字符串哈希可能是另一个比较简单的渠道

课后例题:

1.https://leetcode.cn/problems/construct-string-with-minimum-cost/description/

2.https://leetcode.cn/problems/distinct-echo-substrings/description/

数列哈希:

哈希过程:

利用异或哈希,将每个数字映射成极大域的随机数,将一个串利用异或压缩成一个数字

课上例题:

1.F. The Number of Subpermutations

https://codeforces.com/problemset/problem/1175/F

(思维+预处理值域哈希)

https://codeforces.com/contest/1175/submission/297791258

2.P3792 由乃与大母神原型和偶像崇拜

https://www.luogu.com.cn/problem/P3792

(树状数组维护区间异或值,线段树求max)

https://www.luogu.com.cn/record/193920710

小结:

好用!爱用!

树哈希:

例题:

马蹄杯XY3005

posted @ 2024-12-22 20:23  GsGXT  阅读(132)  评论(0)    收藏  举报