1.哈希定义和整数的散列
空间换时间
给定两个序列,长度分别为n,m,查询后m个数是否在前面n个数中出现过
#include<stdio.h>
const int maxn = 100010;
bool hashTable[maxn] = {false};
int main(){
int m,n,x;
scanf("%d%d",&n,&m);
for(int i = 0;i<n;i++){
scanf("%d",&x);
hashTable[x] = true;
}
for(int i = 0;i<m;i++){
scanf("%d",&x);
if(hashTable[x] == true)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
但是数据不是整数,如字符串则难以处理,所以这时候就用上散列,散列浓缩成一句话:将元素通过函数转换成一个整数,是的该整数尽量唯一地代表这个元素,这个函数称为散列函数H
1) 常用哈希函数
-
直接定址法
H(key) = key 或者线性变换 H(key) = a * key + b -
平方取中法
取key的平方的中间的若干位作为hash值 -
除留余数法
H(key) = key % mod (mod尽量取素数),当两个数的H(key)也就是hash值相同时会产生冲突,需要想办法让第二个key生成新的hash值,下列为解决冲突办法
1)线性探查法:hash+1是否空,不是则使用这个位置,是则hash+2判断(循环)
2)平方探查法:同理,平方变换,H(key) +1^2, H(key) -1^2, H(key) +2^2, H(key) -2^2等等
3)链地址法:将所有H(key)相同的key连成一个单链表
……
2.字符串hash初步
将一个字符串映射为一个整数,a-z或A-Z,对应0-25,25进制数,在转换成十进制数,每个字母唯一对应一个整数,转换的整数最大为26^len - 1。
- 例如只有A-Z时,A-Z对应0-25
int hashTable(char S[],int len){
int id = 0;
for(int i = 0;i<len;i++){
id = id * 26 + (S[i] - 'A');
}
return id;
}
- 含有a-z时,对应26-51,相应转为52进制数
int hashTable(char S[],int len){
int id = 0;
for(int i = 0;i<len;i++){
if(S[i] >= 'A' && S[i] <= 'Z')
id = id * 52 + (S[i] - 'A');
else if(S[i] >= 'a' && S[i] <= 'z')
id = id * 52 + (S[i] - 'a') + 26;
}
return id;
}
- 含有数字
两种处理方式:一是增大到62进制数,二是若是字符串的末尾是确定个数的数字,则将前面字母转换为52进制数,后面数字直接拼接,例如BCD4, BCD 转换为 731 ,则整个字符串转换为 7314 ,下面代码则是具体实现
int hashTable(char S[],int len){
int id = 0;
for(int i = 0;i<len-1;i++){
id = id * 26 + (S[i] - 'A');
}
id = id * 10 + (S[len-1] - '0') ;
具体实例:
给定N个字符串,再给M个查询字符串,问每个查询字符串在N个字符串中出现的次数
#include<stdio.h>
int hashTable1(char S[],int len){
int id = 0;
for(int i = 0;i<len;i++){
id = id * 26 + (S[i] - 'A');
}
return id;
}
int hashTable2(char S[],int len){
int id = 0;
for(int i = 0;i<len;i++){
if(S[i] >= 'A' && S[i] <= 'Z')
id = id * 52 + (S[i] - 'A');
else if(S[i] >= 'a' && S[i] <= 'z')
id = id * 52 + (S[i] - 'a') + 26;
}
return id;
}
int hashTable3(char S[],int len){
int id = 0;
for(int i = 0;i<len-1;i++){
id = id * 26 + (S[i] - 'A');
}
id = id * 10 + (S[len-1] - '0') ;
return id;
}
const int maxn = 100;
char S[maxn][5],temp[5];
int hashTable[26*26*26 + 10];
int hashFunc(char S[],int len){
int id = 0;
for(int i = 0;i<len;i++){
id = id * 26 + (S[i] -'A');
}
return id;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 0;i<n;i++){
scanf("%s",S[i]);
int id = hashFunc(S[i],3);
hashTable[id]++;
}
for(int i = 0;i<m;i++){
scanf("%s",temp);
int id = hashFunc(temp,3);
printf("%d\n",hashTable[id]);
}
return 0;
}