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;
}