字串雜湊模板 例題

2021-10-25 03:12:29 字數 4121 閱讀 9725

核心思想:將字串看成p進製數,p的經驗值是131或13331,取這兩個值的衝突概率低

小技巧:取模的數用2

^64,這樣直接用unsigned

long

long儲存,溢位的結果就是取模的結果

typedef

unsigned

long

long ull;

ull h[n]

, p[n]

;// h[k]儲存字串前k個字母的雜湊值, p[k]儲存 p^k mod 2^64

// 初始化p[0

]=1;

for(

int i =

1; i <= n; i ++

)// 計算子串 str[l ~ r] 的雜湊值

ull get

(int l,

int r)

很久很久以前,森林裡住著一群兔子。

有一天,兔子們想要研究自己的 dna 序列。

我們首先選取乙個好長好長的 dna 序列(小兔子是外星生物,dna 序列可能包含 26 個小寫英文本母)。

然後我們每次選擇兩個區間,詢問如果用兩個區間裡的 dna 序列分別生產出來兩隻兔子,這兩個兔子是否一模一樣。

注意兩個兔子一模一樣只可能是他們的 dna 序列一模一樣。

輸入格式

第一行輸入乙個 dna 字串 s。

第二行乙個數字 m,表示 m 次詢問。

接下來 m 行,每行四個數字 l1,r1,l2,r2,分別表示此次詢問的兩個區間,注意字串的位置從1開始編號。

輸出格式

對於每次詢問,輸出一行表示結果。

如果兩隻兔子完全相同輸出 yes,否則輸出 no(注意大小寫)。

資料範圍

1≤length(s),m≤1000000

輸入樣例:

aabbaabb

31 3 5 7

1 3 6 8

1 2 1 2

輸出樣例:

yesno

yes

模板題,套用上面的模板即可

#include

#include

using

namespace std;

typedef

unsigned

long

long ull;

const

int n =

1000010

, base =

131;

int h[n]

, p[n]

;char str[n]

;int

get(

int l,

int r)

intmain()

int m;

scanf

("%d"

,&m)

;while

(m--

)return0;

}

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

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

輸入格式

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

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

輸出格式

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

每個輸出佔一行。

輸入樣例:

abcbabcbabcba

abacacbaaaab

end輸出樣例:

case 1: 13

case 2: 6

套用字串雜湊演算法。算出正序,逆序雜湊。

列舉中點,然後二分半徑。

技巧:在字元之間插入乙個#,這樣字串長度就變成了偶數,但要注意的是:算原來字元長度的時候

要判斷第乙個字元是什麼,如果不是#,這樣字元長度就是半徑+1,否則就是半徑。

#include

#include

#include

using

namespace std;

typedef

unsigned

long

long ull;

const

int n =

2000010

, base =

131;

char str[n]

;ull hl[n]

, hr[n]

, p[n]

;ull get

(ull h,

int l,

int r)

intmain()

n = n *2;

//注意要更新n

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先想出樸素做法:用乙個下標表示字串字尾的開頭。然後使用快排對這些字尾排序。

比較函式:挨個字元比較。

求兩個字串的最長公共字首長度,可以用字串雜湊的做法。即二分列舉最大長度,如何判斷

這兩個字串是相同的呢?可以求出在這個長度下的字串雜湊值,通過比較雜湊值,判斷在這兩個字串是不是相同的字串。

優化比較函式:可以先求出兩個字尾的最大公共長度,然後比較最大公共長度後乙個字元的大小即可。

#include

#include

#include

#include

using

namespace std;

typedef

unsigned

long

long ull;

const

int n =

300010

, base =

131;

char str[n]

;int sa[n]

;ull h[n]

, p[n]

;int n;

ull get

(int l,

int r)

//二分獲取最大公共長度

intget_max_common_prefix

(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;

}

字串雜湊 模板

以下文字 據我的理解,hash就是乙個像函式一樣的東西,你放進去乙個值,它給你輸出來乙個值。輸出的值就是hash值。一般hash值會比原來的值更好儲存 更小 或比較。那字串hash就非常好理解了。就是把字串轉換成乙個整數的函式。而且要盡量做到使字串對應唯一的hash值。字串hash的種類還是有很多種...

模板 字串雜湊

如題,給定n個字串 第i個字串長度為mi,字串內包含數字 大小寫字母,大小寫敏感 請求出n個字串中共有多少個不同的字串。第一行包含乙個整數n,為字串的個數。接下來n行每行包含乙個字串,為所提供的字串。輸出包含一行,包含乙個整數,為不同的字串個數。s am plei nput sample input...

字串雜湊(模板)

尋找長度為n的主串s中的匹配串t 長度為m 出現的位置或次數屬於字串匹配問題。字串雜湊就是將每個字串轉化為乙個數值,然後遍歷主串,判斷在主串起始位置為i長度為m的字串的雜湊值與匹配串的雜湊值是否相等即可,每次判斷為o 1 的時間。這樣就可以轉化為o n 的時間完成判斷。若求字串中第i位到第j位的雜湊...