唯一の最も一般的なバイナリのハッシュを議論します。
例
質問の意味:異なる文字列をどのように多くの模索($ N \の当量10 ^ 4 $)がN文字列。
分析:
異なるハッシュ値が統計的にあり、次にどのように多くの、各文字列のハッシュ値を求めます。
シングルハッシュ
大きな素数、または自然のオーバーフローを選択します。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの長い 長いLL。 typedefの符号なしの長い 長いULL。 CONST ULLの基地 = 233 。 ULL MOD = 212370440130137957ll。 const int型 MAXN = 10000 + 10 。 int型のn; ULL F [MAXN]。 チャーS [MAXN]。 ULLハッシュ(CHAR S []) // 自然溢出 { ULL ANS = 0 。 int型のlen =STRLEN(S); 以下のために(int型 i = 0 ; iがLEN <; iは++ ) { ANS =(ベース * ANS +(ULL)S [i])と%MOD。 } 戻りANS。 } 設定 <ULL> ST。 INT メイン() { scanf関数(" %のD "、&N) 以下のために(int型 i = 0 ; iがn <; iは++ ) { scanf関数(" %sの" 、S); st.insert(ハッシュ(S))。 } のprintf(" %d個の\ n " 、st.size())。 }
ダブルハッシュ
2つのモジュラ、ハッシュ衝突確率の使用がはるかに低くなるが、一定増加します。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの長い 長いLL。 typedefの符号なしの長い 長いULL。 CONST ULLの基地 = 233 。 ULL MOD1 = 212370440130137957ll。 ULL MOD2 = 1 << 30 。 const int型 MAXN = 10000 + 10 。 int型のn; チャーS [MAXN]。 ULL HASH1(CHAR S []) // 自然溢出 { ULL ANS =0 ; INT LEN = STRLEN(S)。 以下のために(int型 i = 0 ; iがLEN <I ++の) { ANS =(ベース * ANS +(ウール)S [I])%MOD1と、 } 戻りANS; } ウールHASH2(CHAR S []) // 自然溢出 { ウールANS = 0 。 INT LEN = STRLEN(S)。 以下のために(int型 i = 0 ; iがLEN <I ++の) { ANS =(ベースを* ANS +(ULL)S [i])と%MOD2。 } 戻りANS。 } 構造体ノード{ ULLのX、Y。 } [MAXN] F。 BOOL CMP(ノード、ノードB) { 場合(AX == BX) 戻り AY < によって、 リターン斧< BX。 } int型のmain() { scanf関数(" %のD "、&N) 以下のために(int型 i = 0 ; iがn <; iは++ ) { scanf関数(" %sの" 、S); F [i]が.X= HASH1(S)。 F [i]が.Y = HASH2(S)。 // のprintf( "%LLD%LLD \ n"は、[I] .X、[I] .Y F、F)。 } ソート(F、F + N、CMP)。 int型 CNT = 1 ; 用(int型 iは= 0 ; iがN- < 1 ; iが++ ) { 場合([I + F 1 .X] = [I] .X || F [I + F!1 ] .Y = [I] .Y fは! )CNT ++ ; } のprintf(" %d個の\ n " 、CNT)。 }
参考リンク:https://www.cnblogs.com/henry-1202/p/8868414.html