Hash表

hash表

  • hash表
  1. 存储方式
  2. 开放寻址法
  3. 拉链法
  4. 字符串hash
    离散化实际上就是一种特殊的哈希方式【单调递增】

拉链法

如果有一个数是冲突的,用一条链将他们栓起来,像邻接表一样

void insert(int x)
{
int k =((x % N) + N) % N;
e[idx] = x;
ne[idx] = h[k];
h[k] = idx ++;


}

插入数,h存头节点,e存真实际值

e[idx] = x;

存值

ne[idx] = h[k];

next指针指向下一行

h[k] = idx ++;

h[k]指向上一行

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;


}

查找数,图·的遍历方式差不多

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>

using namespace std;
const int N = 100003;
int n,h[N],ne[N],e[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;


}

int main()
{
cin >> n;
memset(h,-1,sizeof h);
while(n--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
if(op[0]=='I')insert(x);
else if(find(x))puts("Yes");
else puts("No");
}


}

开放寻址法

N = 200003;

注意

开放寻址法一般要开到题目数据2~3倍以上

while(h[k]!=Null &&h [k]!=x)
{
k++;
if(k == N) k = 0;
}

h[k]!=Null &&h [k]!=x当前位置是空就往后走

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>

using namespace std;
const int N = 200003,Null = 0x3f3f3f3f;
int n,h[N];


int find(int x)
{
int k = (x % N + N) % N;
while(h[k]!=Null &&h [k]!=x)
{
k++;
if(k == N) k = 0;
}
return k;


}


int main()
{
cin >> n;
memset(h,0x3f,sizeof h);
while(n--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
if(*op=='I') h[find(x)] = x;
else
{

if(h[find(x)] != Null)puts("Yes");
else puts("No");
}



}
return 0;


}

字符串前缀哈希法

\(str = "abcdhhj"\)

\(h_1 = "a"\)

\(h_2 = "ab"\)

\(....\)

\(h_7 ="abcdhhj"\)

特别的 \(h_0 =0\)

注意:\(h\)存的是\(str\)的哈希值

\(A B C D\)

A B C D
1 2 3 4

可看成\(P\)进制下的

\(1 \times p^3 +2\times p^2 +3\times p +4\times p^0\)

\((1 \times p^3 +2\times p^2 +3\times p +4\times p^0)modQ\)
将任何一个数映射到[0,Q-1]
一般情况下不能将字母映射成\(0\)
AAA
假定\(R_p\)足够好完全不考虑冲突,当 \(p= 131\)\(p=13331\)\(Q=2^{64}\)
\(99.99\)%的情况下不会出现冲突

unsigned long long

存储hash值

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>

using namespace std;

typedef unsigned long long ULL;

const int N = 1000010,P=131;

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()
{
int n,m;
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,r1,l2,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
if(get(l1,r1)==get(l2,r2)) puts("Yes");
else puts("No");
}
return 0;


}
posted @ 2022-07-12 22:16  Erfu  阅读(21)  评论(0编辑  收藏  举报