AcWing 841 字串雜湊

2021-09-27 06:06:06 字數 1612 閱讀 8824

題目描述:

給定乙個長度為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

分析:

本題考察字串hash,之前寫過關於字串hash的題解見acwing 138 兔子與兔子。

下面再次回憶下字串hash的具體過程,以加深印象。

我們知道,判斷兩個整數是否相等的時間複雜度是o(1)的,而比較兩個字串是否相等的時間複雜度是o(n)的,如果能夠將字串都對映為乙個整數,那個便可在o(1)的時間內判斷字串是否相等了。每個字元都對應乙個ascii,將單個字元對映為乙個數字並不困難。而對於乙個字串,比如abc,只需要將其看作乙個p進製數,求得其對應的十進位制數後再對乙個大的數取模即可得到該字串經過雜湊對映得到的整數了。一般而言,取p = 131或者13331,可以認為衝突的概率接近為0,對於模數可以取2^64,即取unsigned long long型別的最大表示範圍,不用顯示的去取模,超出表示範圍的溢位部分會自動被截斷,達到了只取低64位取模的目的。

例如abc,a = 1,ab = a * 131 + b = 131 + 2,abc = ab * 131 + c。由此很容易可以推出雜湊陣列h[i] = h[i - 1] * base + str[i] - 'a' + 1。既然h[i]表示前i個字元的hash值,那麼如何求得i 到 j字元的hash值呢?與之前推導類似,h[i - 1] * p[j - i + 1]加上i到j之間的hash值即可得到h[j]的雜湊值,所以i到j之間的hash值為h[j] - h[i - 1] * p[j - i + 1],為此,我們需要在求hash值的字首和時對各個位置的權重也用p[i]儲存一下,避免使用時再去計算。

#include #include using namespace std;

typedef unsigned long long ull;

const int maxn = 100005,p = 131;

int n,m;

ull h[maxn],p[maxn];

char s[maxn];

ull get(int l,int r)

int main()

int l1,r1,l2,r2;

while(m--)

return 0;

}

ACWing 841 字串雜湊

給定乙個長n nn的字串s ss,再給定m mm次詢問,每次詢問含四個整數l1,r1,l 2,r2 l 1,r 1,l 2,r 2 l1 r1 l2 r2 問s ss的兩個區間 l1 r1 l 1,r 1 l1 r 1 和 l2 r2 l 2,r 2 l2 r 2 的子串是否相等。如果相等輸出 ye...

AcWing 841 字串雜湊

給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數 l1,r1,l2,r2 請你判斷 l1,r1 和 l2,r2 這兩個區間所包含的字串子串是否完全相同。字串中只包含大小寫英文本母和數字。輸入格式 第一行包含整數n和m,表示字串長度和詢問次數。第二行包含乙個長度為n的字串,字串中只包含大小...

Acwing 841 字串雜湊 字首雜湊

給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數l1,r1,l2,r2,請你判斷 l1,r1 和 l2,r2 這兩個區間所包含的字串子串是否完全相同。字串中只包含大小寫英文本母和數字。輸入格式 第一行包含整數n和m,表示字串長度和詢問次數。第二行包含乙個長度為n的字串,字串中只包含大小寫...