很久很久以前,森林裏住着一羣兔子。
有一天,兔子們想要研究自己的 DNA 序列。
我們首先選取一個好長好長的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 個小寫英文字母)。
然後我們每次選擇兩個區間,詢問如果用兩個區間裏的 DNA 序列分別生產出來兩隻兔子,這兩個兔子是否一模一樣。
注意兩個兔子一模一樣只可能是他們的 DNA 序列一模一樣。
輸入格式
第一行輸入一個 DNA 字符串 S。
第二行一個數字 m,表示 m 次詢問。
接下來 m 行,每行四個數字 l1,r1,l2,r2l1,r1,l2,r2,分別表示此次詢問的兩個區間,注意字符串的位置從1開始編號。
輸出格式
對於每次詢問,輸出一行表示結果。
如果兩隻兔子完全相同輸出 Yes,否則輸出 No(注意大小寫)。
數據範圍
1≤length(S),m≤1000000
思路:我們對其做一個前綴哈希,O(n)處理一下,然後我們就可以O(1)得到任意子串的哈希值。
#include<cstdio>
#include<vector>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6 + 10;
char s[maxn];
ull p[maxn], h[maxn]; //使用ull產生溢出相當於對2^64 取模,避免了低效的取模運算
int main()
{
scanf("%s", s);
int m, n = strlen(s);
scanf("%d", &m);
ull base = 131; //或者13331
p[0] = 1;
for(int i = 0; i < n; ++i)
{
h[i + 1] = h[i] * base + (s[i] - 'a' + 1);
p[i + 1] = p[i] * base;
}
while(m--)
{
int l1, r1, l2, r2;
scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
if(h[r1] - h[l1 - 1] * p[r1 - l1 + 1] == h[r2] - h[l2 - 1] * p[r2 - l2 + 1])
printf("Yes\n");
else printf("No\n");
}
return 0;
}