字串處理之 字串雜湊

2021-09-28 20:39:18 字數 3674 閱讀 8441

字串雜湊,非常非常好用nb的方法,雖然有一定概率會翻車(翻車概率極低),但是這個是真的nb,你如果會這個在大多數場合可以避免掉有一些演算法的學習,比如馬拉車演算法,

你學馬拉車只能處理回文字串,雖然馬拉車是o(n) ,但在非極端測試點的情況下我們可以用字串雜湊來偷雞,字串雜湊簡單好用,比kmp簡單很多。(kmp有不可替代的場合,kmp還是有必要的)字串雜湊能處理非常非常多的情況,話不多說來道經典的題:

給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數l1,r1,l2,r2,請你判斷[l1,r1]和[l2,r2]這兩個區間所包含的字串子串是否完全相同。

字串中只包含大小寫英文本母和數字。

輸入格式

第一行包含整數n和m,表示字串長度和詢問次數。

第二行包含乙個長度為n的字串,字串中只包含大小寫英文本母和數字。

接下來m行,每行包含四個整數l1,r1,l2,r2,表示一次詢問所涉及的兩個區間。

注意,字串的位置從1開始編號。

輸出格式

對於每個詢問輸出乙個結果,如果兩個字串子串完全相同則輸出「yes」,否則輸出「no」。

每個結果佔一行。

#include

#include

#include

#define ull unsigned long long

using

namespace std;

const

int n=

100010

,base=

131;

char str[n]

;ull p[n]

,h[n]

;int n,m;

intget

(int l,

int r)

intmain()

while

(m--

)return0;

}

原理就是用131進製來表示乙個字串(131不容易翻車),原理非常簡單,蒟蒻我筆拙主要是懶 ,如果想聽更好的講解請移步至acwing。還有就是為了保證**查詢速度為o(1)將131n儲存下來.

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

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

輸入格式

輸入將包含最多30個測試用例,每個測試用例佔一行,以最多1000000個小寫字元的形式給出。

輸入以乙個以字串「end」(不包括引號)開頭的行表示輸入終止。

輸出格式

對於輸入中的每個測試用例,輸出測試用例編號和最大回文子串的長度(參考樣例格式)。

每個輸出佔一行。

這是經典的馬拉車的題目(資料量很恐怖,但o(nlogn)不至於炸),但如果我們會字串雜湊一樣可以偷雞。

#include

#include

#include

#define ull unsigned long long

using

namespace std;

const

int n=

2000010

,base=

131;

ull p[n]

,hl[n]

,hr[n]

;char str[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

(str[i-l]

<=

'z')res=

max(res,l+1)

;else res=

max(res,l);}

printf

("case %d: %d\n"

,++t,res);}

return0;

}

可以看見**非常的簡潔,我們防止字串出現偶數,用插孔法把他變成奇數。

然後以所有點為中點二分列舉半徑。**非常的簡單,沒什麼好說的。

字尾陣列 (sa) 是一種重要的資料結構,通常使用倍增或者dc3演算法實現,這超出了我們的討論範圍。

在本題中,我們希望使用快排、hash與二分實現乙個簡單的o(nlog2n)的字尾陣列求法。

詳細地說,給定乙個長度為 n 的字串s(下標 0~n-1),我們可以用整數 k(0≤k把字串s的所有字尾按照字典序排列,排名為 i 的字尾記為 sa[i]。

額外地,我們考慮排名為 i 的字尾與排名為 i-1 的字尾,把二者的最長公共字首的長度記為 height[i]。

我們的任務就是求出sa與height這兩個陣列。

輸入格式

輸入乙個字串,其長度不超過30萬。

輸出格式

第一行為陣列sa,相鄰兩個整數用1個空格隔開。

第二行為陣列height,相鄰兩個整數用1個空格隔開,我們規定height[1]=0。

字尾陣列,很多被這個題目的名字給嚇到了,我沒學過字尾陣列怎麼辦,沒關係,我也不會 我們可以用字串雜湊偷雞,先看**。

#include

#include

#include

#include

#define ull unsigned long long

using

namespace std;

const

int n=

300010

,base=

131;

char str[n]

;ull h[n]

,p[n]

;int n,sa[n]

;ull get

(int l,

int r)

intget_common_pre

(int a,

int b)

return l;

}bool

cmp(

int a,

int b)

intmain()

sort

(sa+

1,sa+n+

1,cmp)

;for

(int i=

1;i<=n;i++

)printf

("%d "

,sa[i]-1

);puts(""

);for(

int i=

1;i<=n;i++

)puts(""

);return0;

}

我們利用字串雜湊+快排+二分完成偷雞。

假設字串"ponoiiipoi" n=10

字尾陣列的意思就是:

istr10i

9oi8poi

7ipoi

6iipoi

5iiipoi

4oiiipoi

3noiiipoi

2onoiiipoi

1ponoiiipoi

我們利用字串雜湊的特點用二分法求得兩個字尾陣列的最長公共字首,然後完成cmp函式,快排就得到了答案,**非常的簡潔,這樣就避免了那些,我們看不懂的高階演算法了。~ 。~

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進製肯定是唯一的,由此便可實現將字串對映為整數的需求 ...