AcWing 字串雜湊 字串查詢

2021-09-26 09:43:45 字數 1769 閱讀 4888

時/空限制:1s / 64mb

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

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

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

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

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

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

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

每個結果佔一行。

1≤n,m≤10^5

8 3

aabbaabb

1 3 5 7

1 3 6 8

1 2 1 2

yes

noyes

題意:判斷[l1,r1]和[l2,r2]這兩個區間所包含的字串子串是否完全相同。

思路:將字串看成p進製數(判斷兩個整數是否相等好判斷),p的經驗值是131或13331,取這兩個值的衝突概率低。

根據定義分別求出hash[i]:

現在我們想求s3s4的hash值,不難得出為s3∗p+s4,並且從上面觀察,如果看hash[4]−hash[2]並將結果中帶有s1,s2係數的項全部消掉,就是所求。但是由於p的階數,不能直接消掉,所以問題就轉化成,將hash[2]乘乙個關於p的係數,在做差的時候將多餘項消除,從而得到結果。

不難發現,對應項係數只差乙個p^2,而4-3+1=2(待求hash子串下標相減再加一),這樣就不難推導出來此例題的求解式子。hash[4]−hash[2]∗p^(4−2+1)

至此,通過對上例的歸納,可以得出如下的公式:

若已知乙個|s|=n的字串的hash值,hash[i],1≤i≤n,其子串sl..sr,1≤l≤r≤n對應的hash值為:

考慮到hash[i]每次對p取模,進一步得到下面的式子:hash=(hash[r]−hash[l−1]∗p^(r−l+1))%mod。

注意到括號裡面有可能是負數,故:hash=((hash[r]−hash[l−1]∗p^(r−l+1))%mod+mod)%mod。

至此得到求子串hash值公式。取模的數用2^64,這樣直接用unsigned long long儲存,溢位的結果就是取模的結果。

accepted code:

/* 

* @author: lzyws739307453

* @language: c++

*/#include using namespace std;

const int p = 131;

const int maxn = 1e5 + 5;

typedef unsigned long long ull;

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

char str[maxn];

// 初始化

void init(int n)

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

ull get(int l, int r)

int main()

return 0;

}

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