字串雜湊,即把字串轉化為乙個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之後,它便會和你算筆總賬,表...