給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數l1,r1,l2,r2,請你判斷[l1,r1]和[l2,r2]這兩個區間所包含的字串子串是否完全相同。
字串中只包含大小寫英文本母和數字。
輸入格式
第一行包含整數n和m,表示字串長度和詢問次數。
第二行包含乙個長度為n的字串,字串中只包含大小寫英文本母和數字。
接下來m行,每行包含四個整數l1,r1,l2,r2,表示一次詢問所涉及的兩個區間。
注意,字串的位置從1開始編號。
輸出格式
對於每個詢問輸出乙個結果,如果兩個字串子串完全相同則輸出「yes」,否則輸出「no」。
每個結果佔一行。
/*根據定義分別求出hash[i]
hash[1]=s1hash[1]=s1
hash[2]=s1∗p+s2hash[2]=s1∗p+s2
hash[3]=s1∗p2+s2∗p+s3hash[3]=s1∗p2+s2∗p+s3
hash[4]=s1∗p3+s2∗p2+s3∗p+s4hash[4]=s1∗p3+s2∗p2+s3∗p+s4
hash[5]=s1∗p4+s2∗p3+s3∗p2+s4∗p+s5hash[5]=s1∗p4+s2∗p3+s3∗p2+s4∗p+s5
現在我們想求s3s4的hash值,不難得出為s3∗p+s4,並且從上面觀察,如果看hash[4]−hash[2]並將結果種帶有s1,s2係數的項全部消掉,
就是所求。但是由於p的階數,不能直接消掉,所以問題就轉化成,將hash[2]乘乙個關於p的係數,在做差的時候將多餘項消除,從而得到結果。
不難發現,對應項係數只差乙個p2,而4 - 3 + 1 = 2(待求hash子串下標相減再加一),這樣就不難推導出來此例題的求解式子。
hash[4]−hash[2]∗p4−2+1
至此,通過對上例的歸納,可以得出如下的公式。
公式若已知乙個|s|=n|s|=n的字串的hash值,hash[i],1≤i≤n,其子串sl..sr,1≤l≤r≤n對應的hash值為:
hash=hash[r]−hash[l−1]∗p[r−l+1]
*/const
int n =
100010
, p =
131;
// 這裡的p 是經驗值 131 ,或者13331
int n,m;
char str[n]
;// 這裡用unsigned long long 儲存就相當於mod 2 ^ 64, 因為超過了會溢位的
ull h[n]
, p[n]
;// h是儲存字串雜湊值的 p 是儲存p次方的
ull get
(int l,
int r)
intmain()
while
(m --
)return0;
}
字串演算法 字串雜湊
方法以,m進製的形式來表示乙個字串,那麼這個字串就可以輕鬆計算 i j 之間的hash值 當只有小寫 大家字母時,m 131 而hash值,可以使用unsigned long long 來表示,這時不再需要求餘 方法應用 字串匹配。思路 對比hash值 允許k次失配的字串匹配 即 允許k次字元值不對...
字串匹配 雜湊演算法
尋找字串s中字串t出現的位置或次數的問題屬於字串匹配問題。我們接下來討論中假設s的字串長度為 n,t的長度為m。最樸素的想法是,列舉所有起始位置,再直接檢查 是否匹配,複雜度為o nm 的演算法。還有幾個為高效的演算法。而在此我們只介紹實現起來較為容易,而在一些稍作變化的問題中同樣適用,並且可以簡單...
字串雜湊
參照演算法筆記p109,甲級1039 先假設字串均由大寫字母a z構成。在這個基礎上,不妨把a z視為0 25,這樣就把26個大寫字母對應到了26進製中。接著,按照將26進製轉化為10進製的思路,由進製的轉換結論可知,在進製轉換過程中,得到的10進製肯定是唯一的,由此便可實現將字串對映為整數的需求 ...