大力出奇蹟 字串雜湊

2021-09-18 04:56:41 字數 2955 閱讀 7916

字串雜湊,即把字串轉化為乙個bas

ebase

base

進製的數字

把字串a看做乙個base進製的數字, 則a的每個字首的雜湊值為

h as

h[i]

hash[i]

hash[i]==

=(has

h[i−

1]∗b

ase+

a[i]

)%mo

d(hash[i-1] * base + a[i]) \% mod

(hash[

i−1]

∗bas

e+a[

i])%

mod其中,bas

ebase

base

和m od

modmo

d一般取質數,可以減小衝突

把h as

hhash

hash

陣列定義為無符號型別,可以不模,使其自然溢位

然鵝單雜湊容易被卡,最好使用雙雜湊

取不同的base和mod,做兩次雜湊,得到兩組值:has

h1[]

,has

h2[]

hash1, hash2

hash1[

],ha

sh2[

]此時原串的雜湊值為乙個pai

rpair

pair

實測雙雜湊不會慢太多,可放心使用。

觀察每個字首串的雜湊值可得:

h as

h[l,

r]=h

ash[

r]−h

as[l

−1]∗

base

r−l+

1hash[l, r] = hash[r] - has[l-1]*base^

hash[l

,r]=

hash

[r]−

has[

l−1]

∗bas

er−l

+1(當hash不為無符號數時,減法後取模需%mo

d+mo

d)%m

od

\%mod + mod) \% mod

%mod+m

od)%

mod)

於是可以o(1

)o(1)

o(1)

求得任意子串的雜湊值。

簡單的說,字串雜湊可以在字串匹配的過程中,把兩個字串的比較轉化為兩個數字的比較,在時間上消掉乙個n

nn

題目鏈結

題意:兩個串的最長公共子串

(聽說字尾自動機能o(n

)o(n)

o(n)

求。晚點再補兩份字尾陣列&

&\&\&

&&字尾自動機的**。)

預處理出a和b每個字首的雜湊值

因為最長公共子串的性質,存在長度為m

mm的最長公共子串,就一定存在長度為m−1

m-1m−

1的最長公共子串。

所以可以二分答案

check的時候,把a長度為m的所有子串的雜湊值排序,對b的每個長度為m的雜湊值,在有序序列中二分查詢,能找到則check函式返回1。

時間複雜度:check裡面一次排序nlo

gn

nlogn

nlog

n, 二分答案log

nlogn

logn

,一共nlo

g2

nnlog^2n

nlog2n

。看到一種更好的做法 ,把check中排序+二分的操作換成雜湊,可以再消掉乙個log

loglo

g…這裡放乙個雙雜湊的nlo

g2

nnlog^2n

nlog2n

的**。

#include

#include

#include

#include

#include

using namespace std;

typedef

unsigned

long

long ull;

typedef

long

long ll;

typedef pair puu;

const

int base1 =31;

const

int base2 =

196613

;puu has1[

100005

], has2[

100005];

ull p1[

100005

], p2[

100005];

void

hash

(const string &a, puu has)

;int len = a.

size()

;for

(int i =

1; i < len;

++i)

}puu sub

(int l,

int r, puu has)

ull lena, lenb;

vector h;

bool ok

(int n,

int lena,

int lenb)

return0;

}string a, b;

intmain()

int l =

1, r =

min(a.

size()

, b.

size()

), m;

while

(l <= r)

cout << r;

return0;

}

大力出奇蹟 字串雜湊

字串雜湊,即把字串轉化為乙個bas ebase base 進製的數字 把字串a看做乙個base進製的數字,則a的每個字首的雜湊值為 h as h i hash i hash i has h i 1 b ase a i mo d hash i 1 base a i mod hash i 1 bas e...

大力出奇蹟 立方質數

題目描述 如果乙個質數能被表示為三個不同的質數的和的形式,那麼我們稱它為立方質數。現在給你乙個數n,判斷它是不是立方質數。輸入資料 正整數n,n 1000 輸出資料 yes或者no 樣例輸入 19樣例輸出 yes思路 找到小於n的所有質數,從裡面找出符合條件的立方質數。這個思路上應該是比較順暢的,我...

B 爆零 大力出奇蹟

程式設計思維作業和實驗使用的實 測系統,具有及時獲得成績排名的特點,那它的功能是怎麼實現的呢?我們千辛萬苦懟完了不忍直視的程式並提交以後,評測系統要麼返回ac,要麼是返回各種其他的錯誤,不論是怎樣的錯法,它總會給你記上一筆,表明你曾經在這兒被坑過,而當你歷經千辛終將它ac之後,它便會和你算筆總賬,表...