資料結構基礎 字串Hash

2021-10-02 07:14:16 字數 3504 閱讀 2644

取一固定值p,把字串看作p進製數,並分配乙個大於0的數值,代表每種字元。一般般來說,我們分配的數值都遠小於p。例如,對於小寫字母構成的字串,可以令a = 1,b = 2, z = 26。取一固定值m,求出該p進製數對m的餘數,作為該字串的hash值。

字串hash函式把乙個任意長度的字串對映成一乙個非負整數,並且其衝突概率幾乎為零。

根據經驗,取p = 131p = 13331,此時hash 值產生衝突的概率極低,只要hash值相同,我們就可以認為原字串是相等的。通常我們m=2^64,即直接使用unsigned long long型別儲存這個hash值,在計算時不處理算術溢位問題,產生溢位時相當於自動對2^64取模,這樣可以避免低效的取模(mod) 運算。

對字串的各種操作,都可以直接對p進製數進行算術運算反映到hash值上。如果我們已知字串s的hash 值為h(s), 那麼在s後新增乙個字元c構成的新字串s+c的hash值就是h(s +c) = (h(s)*p + value[c]) modm。其中乘p就相當於p進製下的左移運算,value[c] 是我們為c選定的代表數值。

如果我們已知字串s的hash值為h(s), 字串**s+t的hash值為h(s +t),那麼字串t的hash值h(t)= (h(s +t)- h(s)* plength(t) modm.**這就相當於通過p進製下在s後邊補0的方式,把s左移到與s+t的左端對齊,然後二者相減就得到了h(t)。

例如:

s= 「abc」, c= 「d」,t= 「xyz」,則:s表示為p進製數: 123

h(s)= 1p^2+2p+3

h(s+c)=1*p3 +2*p2 +3*p+4=h(s)*p+4

s+t表示為p進製數:123242526

h(s+t)=1*p5+2*p4+3*p3+24*p2+25*p+26

s在p進製下左移length(t) 位: 123000

二者相減就是t表示為p進製數: 24 2526

h(t)=h(s+t)-(1*p2 +2+p+3)*p3=24*p2 +25*p+26

根據上面兩種操作,我們可以通過0(n)的時間預處理字串所有字首hash值,並在0(1) 的時間內查詢它的任意子串的hash值。

題目大意:

很久很久以前,森林裡住著一群兔子。有一天,兔子們想要研究自己的dna序列。我們首先選取乙個好長好長的dna序列(小兔子是外星生物,dna序列可能包含26個小寫英文本母),然後我們每次選擇兩個區間,詢問如果用兩個區間裡的dna序列分別生產出來兩隻免子,這兩隻兔子是否一模一樣。注意兩隻兔子一模一樣只可能是它們的dna序列一模一樣。1 <= length(s),q <= 10^6。

思路:

記我們選取的dna序列為s,根據我們剛才提到的字串hash演算法,設f[i]表示字首子串s[1~i] 的hash值,有f[i=f[i-1]*131+(s[i]- 「a」+1).於是可以得到任一區間 [l.r] 的hash值為f[r] - f[i-1] * 131 - i + 1。當兩個區間的hash 值相同時,我們就認為對應的兩個子串相等。整個演算法的時間複雜度為o([s| + q)。

**:

#include

#include

#include

using

namespace std;

typedef

unsigned

long

long ull;

const

int n =

1000010

;char s[n]

;ull sum[n]

, p[n]

;int

main()

for(

int i =

1; i <= t; i++

)return0;

}

題目大意:

如果乙個字串正著讀和倒著讀是一樣的,則稱它是回文的。

給定乙個長度為n的字串s,求他的最長回文子串的長度是多少。

輸入樣例:

abcbabcbabcba

abacacbaaaab

end

輸出樣例:

case 1:13

case 2

:6

思路:

求出正序和逆序的hash值, 再遍歷每個點,以每個點為中心,二分查詢以它為中心的回文串的最大寬度。由於要分奇偶兩種情況討論,可以在字串的每兩個字元插入乙個不會用的的字元,將字元變為奇數。

列如:

abca#b#c

abcd

a#b#c#d

這樣就可以只討論奇數的情況。

**:

#include

#include

#include

using

namespace std;

const

int n =

2000010

, base =

131;

typedef

unsigned

long

long ull;

char s[n]

;ull hl[n]

, hr[n]

, p[n]

;ull get

(ull h,

int l,

int r)

intmain()

n *=2

; p[0]

=1;for

(int i =

1, j = n; i <= n; i++

, j--

)int res =0;

for(

int i =

1; i <= n; i++)if

(s[i - l]

<=

'z') res =

max(res, l +1)

;else res =

max(res, l);}

printf

("case %d: %d\n"

, c++

, res);}

return0;

}

資料結構 字串

1 字串 include string.h include stdio.h include stdlib.h include math.h include time.h define ok 1 define error 0 define true 1 define false 0 define ma...

資料結構 字串

字串是由0個或多個字元構成的序列,可記為s a1a2a3 an 其中ai可以是字母,也可是數字或者其他字元,零個字元的串稱為空串。而字串的順序結構就是用簡單的char型別陣列來儲存沒什麼好說的,下面介紹一下bf演算法與kmp演算法 bf演算法就是比較平常的雙重迴圈,如果匹配成功打斷迴圈,否則子串的比...

資料結構 字串

靜態陣列實現 順序儲存 串的順序儲存 define maxlen 255 預定義最大串長為255 typedef struct 靜態陣列實現 順序儲存 sstring 動態陣列實現 堆分配儲存 typedef struct 動態陣列實現 堆分配儲存 hstring 初始化void inithstri...