ACM入门之哈希
Posted 辉小歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM入门之哈希相关的知识,希望对你有一定的参考价值。
哈希在竞赛中也是一个很常用,且非常厉害的一个算法。
哈希的主要思想就是把一个东西转换成一个大整数,这样比较两个东西是否相等的就只要比较两个整数是否相等就行了,
比较的时间复杂度是O(1)的。
举一个比较常见的例子:比较俩字符串是否相等,我们可以将字符串变成一个值,然后直接比较这俩字符串的哈希值就行了。
可能你会有疑问?在c++中string 不是可以直接就比较了么? 为啥还要用哈希呢?
假如人家问的是俩矩阵是否相等呢?假如人家问这个矩阵是否在一个大矩阵中出现过呢?
那么如何存矩阵呢?我们就可以用二维哈希,将矩阵也映射成一个哈希值,这样比较矩阵直接比较哈希值就行了。
其实,通过上面你已经对哈希有了一个初步的了解了。哈希它其实就是将一些特别难存的东西,通过某种手法变成一个唯一的值,
然后只需比较哈希值就行了。
哈希常见的几种模型:
- 一维哈希(字符串)
- 二维矩阵哈希
核心思想:将字符串看成P进制数,P的经验值是131,13331,233,2333,10007等质数 取这些值的冲突概率低
取模的时候选一个较大的质数避免冲突。
小技巧:取模的数用2^64,这样直接用unsigned long long存储,溢出的结果就是取模的结果
一维哈希模板:
typedef long long int LL;
const int M=233;//是我们自己选择的进制数,一般可以选233,2333,10007等质数
const int mod=1e9+7;//一般选一个比较大的质数
LL get(string s)//获取字符串对应的哈希值
LL sum=0;
for(int i=0;i<s.size();i++) sum=(sum*M+s[i]-'a')%mod;
return sum;
typedef unsigned long long int ull;
const int N=1e5+10;
const int M=233;
ull h[N],base[N];
ull query(int l,int r)//获取字符串[l,r]的哈希值
return h[r]-h[l-1]*base[r-l+1];
void init(string s)//初始化哈希
int n=s.size();
s="0"+s;//让其下标从1开始
base[0]=1;
for(int i=1;i<=n;i++)
h[i]=h[i-1]*M+s[i];
base[i]=base[i-1]*M;// base[i]=M^i
ull merge(int l1, int r1, int l2, int r2)
//求[l1,r1],[l2,r2]子串并的哈希值
return query(l1, r1) * base[r2 - l2 + 1] + query(l2, r2);
字符串哈希入门:
P3370 【模板】字符串哈希
841. 字符串哈希
103. 子串查找
二维哈希模板
typedef long long int ll;
const int N=1010;
ll h[N][N],base1[N],base2[N];
int a[N][N],n,m;
void init()//构建
base1[0]=base2[0]=1;
for(int i=1;i<N;i++)
base1[i]=base1[i-1]*131;
base2[i]=base2[i-1]*233;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
h[i][j]=h[i][j-1]*131+a[i][j];//行哈希
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
h[i][j]=h[i-1][j]*233+h[i][j];//列哈希
ll query(int x1,int y1,int x2,int y2)//查询矩阵的哈希值
return h[x2][y2]-h[x2][y1-1]*base1[y2-y1+1]-h[x1-1][y2]*base2[x2-x1+1]
+h[x1-1][y1-1]*base1[y2-y1+1]*base2[x2-x1 + 1];
以上是关于ACM入门之哈希的主要内容,如果未能解决你的问题,请参考以下文章