字串雜湊(8848,兩個密碼 霧) 雜湊表

2022-07-30 05:33:21 字數 3934 閱讀 3950

對於我來說,hash就像乙個加密軟體,你輸入乙個值,他就會輸出值,並且比之前的值更優,更方便。而這個值呢,就叫做雜湊值。然後字串雜湊就是輸入乙個字串,把它轉成對應的hash值就行了。

對於每個字串,我們通過乙個固定的轉換方式,使相同字串的雜湊值一定相同,不同字串的值盡量不同。因為很可能存在兩個不同的字串雜湊值一樣的操作,我們稱之為「雜湊衝突」

我們此處傳換的方式,就是最常見的進製雜湊,它的核心是給出乙個固定進製base,把字串上面的每乙個元素看成base進製的每乙個數字,然後轉換成十進位制,最後的結果就是hash值。最後我們只需要比較每乙個字串的hash值就可以知道他們是不是同乙個字串。

關於進製的選擇,還是很自由的,但是一定不要含有mod的質因子(那你還模什麼模),所以我們取進製和mod時,一般都是質數。但是簡單的還是利用unsigned long long,不手動進行取模,它溢位時會自動對264

'>2^64取模

如題,給定n個字串(第i個字串長度為mi,字串內包含數字、大小寫字母,大小寫敏感),請求出n個字串中共有多少個不同的字串。

輸入格式:

第一行包含乙個整數n,為字串的個數。

接下來n行每行包含乙個字串,為所提供的字串。

輸出格式:

輸出包含一行,包含乙個整數,為不同的字串個數。

輸入樣例1

5

abcaaaa

abcabcc

12345

輸出樣例1

4

對於這個雜湊,我們不對它取模,而是利用unsigned long long的溢位取模。

1 #include2

#define fast std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)

3using

namespace

std;

4 typedef unsigned long

long ull;//

typedef專門把c++的值的型別改名字,和巨集定義乙個道理,如自帶的int,char或者自定義的struct

5int n,ans=1;//

種類因為不搜第乙個,所以初值是一

6 ull base=131;//

進製數

7int a[10001];//

記錄hash值

8int hash(strings)9

15return sum;//

返回hash值 16}

17int

main()

1827 sort(a+1,a+1+n);//

hash值排序

28for(int i=2;i<=n;i++)

2932 cout<33 }

自定義取模的值就行了。

1 #include2

#define fast std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)

3using

namespace

std;

4int mod=20160817;//

神奇的數字(質數)但是交上去只能得80分,所以我們用乙個大一點的質數(212370440130137957ll) 不要在意後面的兩個符號,交上去就對了

5int n,ans=1;6

long

long

base=131;7

int a[100001];8

int hash(strings)9

16return sum;//

返回hash值 17}

18int

main()

1928 sort(a+1,a+1+n);//

hash值排序

29for(int i=2;i<=n;i++)

3033 cout<34 }

這其實就是你用不同的兩種或多種方式雜湊,然後分別比對每一種雜湊值是否相同——顯然是增加了空間和時間,但也確實增加了其正確性。

1 #include2

#define fast std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)

3using

namespace

std;

4int mod1=20160817;5

int mod2=19260817; 6

int n,ans=1;7

intbase=131;8

struct

nodea[100001

];11

int hash1(string

s)12

19return

sum;20}

21int hash2(string

s)22

29return sum;//

返回hash值 30}

31bool

sj(node x,node y)

3235

intmain()

3646 sort(a+1,a+1+n,sj);//

hash值排序

47for(int i=2;i<=n;i++)

4851 cout<52 }

說到底,我們雜湊還是來分辨字串的。有人說:字串不可以用map嗎?

可以的,但是你要知道,map是o(n)的,而雜湊只需要計算一下,就直接找到,o(1)的,所以明白了嗎?

這就是hash_map,也叫雜湊表

雜湊表呢,就是開一串陣列,然後每乙個字串對應乙個下標,而這個下標,就是他的雜湊值(因為這裡的陣列開不了很大,所以一般不用自然溢位)

所以就存在雜湊值重複的情況,我們這裡有三種操作方式

當雜湊值衝突的時候,我們就可以用鏈式前向星(就和那個存圖一樣的)

void add(int

x)

這裡的key是雜湊值,last[i]是最後乙個雜湊值為i的編號,然後pre就是上乙個,連起來就行了。查詢的時候就像基本的前向星一樣查詢就是了,乙個乙個向上遍歷

這裡要提醒一下,當你的mod大,陣列就大,空間就大,相應的衝突就小,所以時間就比較快。而mod小了,陣列就小,空間小,相應的衝突大,所以時間就會慢,有的時候會超時。

這裡的線性勘測法就是有衝突的,下標就加一,如果還有,就繼續加一......

1

void add(intx)2

找的時候一樣

bool find(int

x)

所以這個時間複雜度還是很麻煩的,因為你會發現元素都是堆在一堆的,查詢很慢,所以我們要跳來跳去

這個用的就是平方跳跳跳,1^2,-1^2,2^2.......(s是平方陣列)

void add(int

x) sum[key].x=x;

}

1

bool find(intx)2

10if(!sum[key].x)return

false;11

return

true

;12 }

因為這種方法存在一直在跳迴圈,所以陣列空間最好開大點......

兩個輔助變數挖字串

1 有乙個字串符合以下特徵 abcdef,acccd,eeee,aaaa,e3eeeee,sssss,要求寫乙個函式 介面 輸出以下結果 1 以逗號分割字串,形成二維陣列,並把結果傳出 2 把二維陣列行數運算結果也傳出.2 請自己定義乙個介面 函式 要求1 能正確表達功能的要求,定義出介面 函式 3...

字串處理的兩個問題

處理字元是c語言中的常見操作,有兩個問題需要討論 一是判斷字元處理結束的標誌是空字元還是換行符,二是迴圈處理字元時,迴圈次數是字元陣列的容量大小還是實際輸入字元的個數。舉例 鍵盤輸入一行字元,統計大寫字元的個數。本例可用兩種方法程式設計,第一種方法的 如下 include int main 下面是第...

實現兩個長字串相加

兩個大數相加,且這兩個大數是正整數 暫時不考慮負數,不考慮輸入不合法的情況 要保證輸入是正確的才能保證程式正常執行 include include define maxsize 1000 int main temp1 j 0 j 0 for i len2 1 i 0 i 2.把兩個字串補齊,即短字串...