變成字串 字串雜湊 從零開始的十分鐘包會教程

2021-10-14 17:35:45 字數 2043 閱讀 3065

好了不跟你多bb,想象你現在有一堆數,你要把他們裝進一堆桶裡,相同的數放在一起,你會怎麼做呢?

哦這太簡單了!只要在每個桶上面標上這個數,然後把數丟進相應的桶不就完了?

(咦?怎麼有個桶看起來就很蠢的樣子)

那我們在程式上怎麼實現這個桶呢?

啊答主你是沒學過陣列還是怎麼的!直接開乙個a[1000],假設來了乙個數x,就讓a[x]自加1不就行了!

好啊!但你這有個小問題。要是來乙個9999怎麼辦?開a[10000]?

那要是來99999呢?987654321呢?或者更直接,來個字串呢?

難道要開字串為下標的陣列?這怎麼可能呢。

讓我們想想問題出在哪。下標必須是乙個不太大的正整數,也就是說,我們要將乙個字串變成乙個不太大的正整數。

首先我們將每個字元看做等於他的ascii碼的整數,這樣字串就變成了乙個數串,且每個數不超過127(只有字母和數字的話ascii是不超過127的)。

現在我們就來突發奇想啦!怎麼才能用乙個數表示這個陣列呢?

從前有這樣一種東西,它的每一位都不超過127,也就是說不到128……

啊!這不就是乙個128進製的數嗎!

從左到右,分別代表了這個128進製數的從高位到低位……

然而我們現在知道的是這個數的每一位,要得到這個數是很簡單的。

比如[100,55]這個數有兩位,

那麼這個數的值就是100×128+55=12855

有三位的話,如[127,100,55],

那就是127×(128^2)+100×128+55=2093623

那麼我們只需要提前處理出128的若干次方,然後分別與這個數的每一位相乘,就能得到這個數了!

完美!等等,128的5次方不就超出int範圍了嗎?

超就超!

要知道我們實際上要建立的是乙個單射關係,即只要能通過乙個字串推出乙個唯一確定的數,我們的目的就達到了。

我其實是求出了這個128進製數的值的,只是最後將它對映到了int範圍裡的數。

這時聰明的讀者說:你這樣損失了資訊,萬一兩個128進製數本來不同,這麼一搞給你搞成相同的了那不完犢子了?

考慮到這個數已經很大了,將它mod一下int範圍,其實已經相當於int範圍內的隨機數了,只是這個數是由字串唯一確定的。

既然是隨機數,那不同的字串對映到相同數的概率,就跟在0~2147483647裡隨機取兩個數,它們相等的概率一樣了。

在實際中,我們可以認為這個概率就是0。

完美!!!

當然,現在這個數的範圍是0~2147483647。如果想要繼續縮小範圍,那麼可以再mod乙個隨便什麼數,原理同上。

當然你mod的數也不能太小。具體如果你取n,那麼平均情況下在計算到第1.17*√n個字串時有50%的概率會重複(證明可搜「生日攻擊」)。所以建議在不超過限度的情況下盡量取大。

int gethash(char* s, int length, int range) 

if(answer < 0) answer = -answer; // 必須是非負數

answer %= range;

return answer;

}

Hash 字串 字串雜湊

luo gu luogu luogup 3370 p3370 p337 0如題,給定n個字串 第i個字串長度為mi,字串內包含數字 大小寫字母 請求出n個字串中共有多少個不同的字串。第一行包含乙個整數n,為字串的個數。接下來n行每行包含乙個字串,為所提供的字串。輸出包含一行,包含乙個整數,為不同的字...

字串演算法 字串雜湊

方法以,m進製的形式來表示乙個字串,那麼這個字串就可以輕鬆計算 i j 之間的hash值 當只有小寫 大家字母時,m 131 而hash值,可以使用unsigned long long 來表示,這時不再需要求餘 方法應用 字串匹配。思路 對比hash值 允許k次失配的字串匹配 即 允許k次字元值不對...

字串雜湊

參照演算法筆記p109,甲級1039 先假設字串均由大寫字母a z構成。在這個基礎上,不妨把a z視為0 25,這樣就把26個大寫字母對應到了26進製中。接著,按照將26進製轉化為10進製的思路,由進製的轉換結論可知,在進製轉換過程中,得到的10進製肯定是唯一的,由此便可實現將字串對映為整數的需求 ...