字串雜湊1
一、字串雜湊簡介
Hash,一般翻譯做雜湊、雜湊,或音譯為雜湊,是把任意長度的輸入(又叫做預對映pre-image)通過雜湊演算法變換成固定長度的輸出,該輸出就是雜湊值。這種轉換是一種壓縮對映,也就是,雜湊值的空間通常遠小於輸入的空間,不同的輸入可能會雜湊成相同的輸出,所以不可能從雜湊值來確定唯一的輸入值。簡單的說就是一種將任意長度的訊息壓縮到某一固定長度的訊息摘要的函式。
字串雜湊即當字串過長時若逐位比較時間開銷會很大,這時通過雜湊演算法求出它的雜湊值,利用雜湊值進行比較即可減小時間開銷。這裡要介紹的是最常用的一種雜湊演算法:進位制雜湊。進位制雜湊先給出一個數即進位制,將一個串的每一個元素看做一個進位制位上的數字,然後求出這個串所對應的數,這個數就是這個串的雜湊值,通過比較不同串的的雜湊值來判斷兩個串是否相同,通過這種方法可以大大減少時間複雜度。
二、模板題目-字串雜湊
這道題是一道模板題,很經典,但是很能幫助我們理解雜湊以及明白雜湊的作用。
題目內容
如題,給定 N 個字串(第 i個字串長度為 M_i,字串內包含數字、大小寫字母,大小寫敏感),請求出 N個字串中共有多少個不同的字串。
輸入格式
第一行包含一個整數 N,為字串的個數。
接下來 N 行每行包含一個字串,為所提供的字串。
輸出格式
輸出包含一行,包含一個整數,為不同的字串個數。
輸入輸出樣例
輸入
5
abc
aaaa
abc
abcc
12345
輸出
4
說明/提示
對於30% 的資料:N≤10,M_i≈6,Mmax≤15。
對於 70%70% 的資料:N≤1000,M_i≈100,Mmax≤150。
對於 100%100% 的資料:N≤10000,M_i≈1000,Mmax≤1500。
解題過程
先放上常用模板(出自ACM學長-OHAMEOW隊伍),模板中的131即是前文所提的進位制雜湊中的進位制,MOD選擇一個較大的數(最好是大質數) :
ll BKDR_hash(char *str) {
ll ans = 0;
int len = strlen(str);
for (int i = 0; i < len; i++) {
ans = (ans * 131 + str[i]) % MOD;
// 種子可以是 31、131、1313、13131、131313..
}
return ans;
}
計算每一個字串的雜湊值並存儲在陣列中,計算完畢後利用sort進行排序,再找出有多少個不重複的字串:
sort(hashValue,hashValue+n);
int ans = 1;
for(int i=1;i<n;i++){
if(hashValue[i]!=hashValue[i-1]) ans++;
}
全部程式碼
#include<bits/stdc++.h>
#define MOD 2031111029377612937
using namespace std;
long long int hashValue[10005];
long long int BKDR_hash(string str){
long long int ans = 0;
int len = str.length();
for(int i=0;i<len;i++){
ans = (ans*131 + str[i]) % MOD;
}
return ans;
}
int main(){
int n;
cin >> n;
string s;
for(int i=0;i<n;i++){
cin >> s;
hashValue[i] = BKDR_hash(s);
}
sort(hashValue,hashValue+n);
int ans = 1;
for(int i=1;i<n;i++){
if(hashValue[i]!=hashValue[i-1]) ans++;
}
cout << ans;
}