以洛谷p3370為引子引入吧:
雜湊其實是所有字串操作中,筆者認為最簡單的操作了(except輸入輸出qwq)。雜湊的過程,其實可以看作對乙個串的單向加密過程,並且需要保證所加的密不能高概率重複(就像不能讓隔壁老王輕易地用它家的鑰匙開啟你家門一樣qwq),通過這種方式來替代一些很費時間的操作。
比如,最常見的,當然就是通過雜湊陣列來判斷幾個串是否相同(洛谷p3370)。此處的操作呢,很簡單,就是對於每個串,我們通過乙個固定的轉換方式,將相同的串使其的「密」一定相同,不同的串 盡量 不同。
此處有人指出:那難道不能先比對字串長度,然後比對ascll碼之和嗎?事實上顯然是不行的(比如ab和ba,並不是同乙個串,但是如是做卻會讓其認為是qwq)。這種情況就叫做hashhash衝突,並且在如此的單向加密雜湊中,hashhash衝突的情況在所難免(bzoj就有這種讓你給出一組樣例,使得一段雜湊**衝突的題,讀者可以嘗試嘗試)。
而我們此處介紹的,即是最常見的一種雜湊:進製雜湊。進製雜湊的核心便是給出乙個固定進製basebase,將乙個串的每乙個元素看做乙個進製位上的數字,所以這個串就可以看做乙個basebase進製的數,那麼這個數就是這個串的雜湊值;則我們通過比對每個串的的雜湊值,即可判斷兩個串是否相同
這裡獻上單hash的ac**:
#include
using
namespace std;
typedef
unsigned
long
long ull;
ull a[
10010];
char s[
10010];
int n,ans=1;
int prime=
233317
; ull base=
131;
ull mod=
212370440130137957ll
;ull hashe
(char s)
intmain()
sort
(a+1
,a+n+1)
;for
(int i=
1;i)printf
("%d"
,ans)
;}
再看看安全係數更高的雙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)
ull hash2
(char s)
bool
comp
(data a,data b)
main()
sort
(a+1
,a+n+
1,comp)
;for
(int i=
2;i<=n;i++)if
(a[i]
.x!=a[i-1]
.x || a[i-1]
.y!=a[i]
.y) ans++
;printf
("%d\n"
,ans)
;}
用1e18的質數的hash:
#include
#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)
main()
sort
(a+1
,a+n+1)
;for
(int i=
2;i<=n;i++)if
(a[i]
!=a[i-1]
) ans++
;printf
("%d\n"
,ans)
;}
Hash 字串 字串雜湊
luo gu luogu luogup 3370 p3370 p337 0如題,給定n個字串 第i個字串長度為mi,字串內包含數字 大小寫字母 請求出n個字串中共有多少個不同的字串。第一行包含乙個整數n,為字串的個數。接下來n行每行包含乙個字串,為所提供的字串。輸出包含一行,包含乙個整數,為不同的字...
字串雜湊 Hash
字串雜湊,用通俗點的說法就是將乙個字串轉換成乙個整數,而且用雜湊轉換出來的整數,不同的字串,不出意外整數也不一樣 存在極少的情況一樣 從而更方便地確定某個字串是否重複出現過或者對字串進行其他的判斷。基本思想 假設乙個字串 abcdabcd 將整個字串看成乙個p p一般取131或者13331比較好,可...
字串演算法 字串雜湊
方法以,m進製的形式來表示乙個字串,那麼這個字串就可以輕鬆計算 i j 之間的hash值 當只有小寫 大家字母時,m 131 而hash值,可以使用unsigned long long 來表示,這時不再需要求餘 方法應用 字串匹配。思路 對比hash值 允許k次失配的字串匹配 即 允許k次字元值不對...