學習筆記 雜湊學習筆記

2021-08-08 18:04:20 字數 1847 閱讀 4050

hash基本原理:

hash就是乙個像函式一樣的東西,你放進去乙個值,它給你輸出來乙個值。輸出的值就是hash值。一般hash值會比原來的值更好儲存(更小)或比較。

那字串hash就非常好理解了。就是把字串轉換成乙個整數的函式。而且要盡量做到使字串對應唯一的hash值。

它的主要思路是選取恰當的進製,可以把字串中的字元看成乙個大數字中的每一位數字,不過比較字串和比較大數字的複雜度並沒有什麼區別(高精數的比較也是o (

n )的),但只要把它對乙個數取模,然後認為取模後的結果相等原數就相等,那麼就可以在一定的錯誤率的基礎上

o (1)

進行判斷了。

hash的實現方法:

首先不要把任意字元對應到數字0,比如假如把a對應到數字0,那麼將不能只從hash結果上區分ab和b(雖然可以額外判斷字串長度,但不把任意字元對應到數字0更加省事且沒有任何***),一般而言,把a-z對應到數字1-26比較合適。

關於進製的選擇實際上非常自由,大於所有字元對應的數字的最大值,不要含有模數的質因子(那還模什麼),比如乙個字符集是a到z的題目,選擇27、233、

19260817

都是可以的。

模數的選擇(盡量還是要選擇質數):

絕大多數情況下,不要選擇乙個

10​9

​​級別的數,因為這樣隨機資料都會有hash衝突,根據生日悖論,隨便找上

√​10​

9​​​​​

個串就有大概率出現至少一對hash 值相等的串(參見bzoj 3098 hash killer ii)。

最穩妥的辦法是選擇兩個

10​9

​​級別的質數,只有模這兩個數都相等才判斷相等,但常數略大,**相對難寫,目前暫時沒有辦法卡掉這種寫法(除了卡時間讓它超時)(參見bzoj 3099 hash killer iii)。

如果能背過或在考場上找出乙個

10​1

​​8級別的質數(miller-rabin),也相對靠譜,主要用於前一種擔心會超時,後一種擔心被卡。

偷懶的寫法就是直接使用unsigned long long,不手動進行取模,它溢位時會自動對2​6

​​4進行取模,如果出題人比較良心,這種做法也不會被卡,但這個是完全可以卡的,卡的方法參見bzoj 3097 hash killer i。

//雙hash

#include #include #include using namespace std;

typedef unsigned long long ull;

ull base=131;

struct data

a[10010];

char s[10010];

int n,ans=1;

ull mod1=19260817;

ull mod2=19660813;

ull hash1(char s)

{ int len=strlen(s);

ull ans=0;

for (int i=0;i#include #include using namespace std;

typedef unsigned long long ull;

ull base=131;

ull a[10010];

char s[10010];

int n,ans=1;

ull mod=212370440130137957ll;//是質數!!

ull hashs(char s)

{ int len=strlen(s);

ull ans=0;

for (int i=0;i

雜湊學習筆記

雜湊錶用的是陣列支援按照下標隨機訪問資料的特性,所以雜湊表其實就是陣列的一種擴充套件,由陣列演化而來。可以說,如果沒有陣列,就沒有雜湊表。它是乙個函式。我們可以把它定義成hash key 其中 key 表示元素的鍵值,hash key 的值表示經過雜湊函式計算得到的雜湊值。三點雜湊函式基本要求 開放...

雜湊學習筆記

考慮具有以下形式的方程 a1x13 a2x23 a3x33 a4x43 a5x53 0 係數是從區間 50,50 起的整數。考慮解決方案 x1,x2,x3,x4,x5 來驗證方程xi 50,50 xi!0,任何i 確定滿足給定方程的解數。輸入項 輸入的唯一行包含由空格分隔的5個係數a1,a2,a3,...

雜湊學習筆記

大概日後會更新 零.hash的用途 在資料範圍不大的時候,你完全可以用乙個map或者set來搞定 如果可以用c 11,你還可以用undered map來搞定 然鵝map也是hash實現的 所以當資料範圍很大 你莫得c 11 出題人毒瘤的時候,就需要雜湊 為了愉快的進行hash,下面煮的栗子預設出題人...