Day 5_2 哈希

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) 常用哈希函數

  1. 直接定址法
    H(key) = key 或者線性變換 H(key) = a * key + b

  2. 平方取中法
    取key的平方的中間的若干位作爲hash值

  3. 除留餘數法
    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。

  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;
}
  1. 含有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;
}
  1. 含有數字
    兩種處理方式:一是增大到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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章