哈希表
目的:将大范围的多个数映射到一个0-N的集合中
常见哈希表:
1.普通哈希表
处理冲突方式:
1.开放寻址法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const int N=2e5+3,num=0x3f3f3f3f; int h[N]; int find(int x) { int k=(x%N+N)%N; while(h[k]!=num&&h[k]!=x) { k++; if(k==N)k=0; } }
int k=find(x); h[k]=x;
int k=find(x); if(h[k]!=num) else
|
2.拉链法:一个数组存储所有哈希值
常用操作:1.添加2.查找
3.删除(额外数组进行标记,不常用)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const int N=1e5+3; int h[N],e[N],ne[N],idx;
void insert(int x) { int k=(x%N+N)%N; e[idx]=x; ne[idx]=h[k]; h[k]=idx++; }
bool find(int x) { int k=(x%N+N)%N; for(int i=h[k];i!=-1;i=ne[i]) if(e[i]==x)return true; return false; }
|
2.字符串哈希
字符串前缀哈希法:
预处理所有前缀的哈希
1.如何定义前缀的哈希值:将其转化为p进制数
注:*1.不能将任何数映射为0
*2.不存在冲突时,p=131或13331、Q取2^64时,不存在冲突
好处:可以依照公式求出前缀的哈希值求出一段的哈希值
公式: \[
h[R]-h[L-1]*p^(R-L+1)
\]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int N=1e5+10,P=131; int n,m; char str[N]; ull h[N],p[N]; ull get(int l,int r) { return h[r]-h[l-1]*p[r-l+1]; } int main() { scanf("%d%d%s",&n,&m,str+1); p[0]=1; for(int i=1;i<=n;i++) { p[i]=p[i-1]*P; h[i]=h[i-1]*P+str[i]; } while(m--) { int l1,l2,r1,r2; cin>>l1>>r1>>l2>>r2; if(get(l1,r1)==get(l2,r2))cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }
|