1. 程式人生 > 實用技巧 >兔子與兔子

兔子與兔子

很久很久以前,森林裡住著一群兔子。

有一天,兔子們想要研究自己的 DNA 序列。

我們首先選取一個好長好長的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 個小寫英文字母)。

然後我們每次選擇兩個區間,詢問如果用兩個區間裡的 DNA 序列分別生產出來兩隻兔子,這兩個兔子是否一模一樣。

注意兩個兔子一模一樣只可能是他們的 DNA 序列一模一樣。

輸入格式

第一行輸入一個 DNA 字串 S。

第二行一個數字 m,表示 m 次詢問。

接下來 m 行,每行四個數字 l1,r1,l2,r2<?XML:NAMESPACE PREFIX = "[default] http://www.w3.org/1998/Math/MathML" NS = "http://www.w3.org/1998/Math/MathML" />l1,r1,l2,r2,分別表示此次詢問的兩個區間,注意字串的位置從1開始編號。

輸出格式

對於每次詢問,輸出一行表示結果。

如果兩隻兔子完全相同輸出 Yes,否則輸出 No(注意大小寫)。

資料範圍

1≤length(S),m≤10000001≤length(S),m≤1000000

輸入樣例:
aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2
輸出樣例:
Yes
No
Yes


將字串看成一個p進位制的數,然後用unsigned long long 來儲存,相當於
溢位後自動mod2^64,p一般取131,13331.
此題思路:
將字串的字首轉換為hash值,然後求出p對應得進位制數。
假設字串為
abcd
對應的字首hash為
h[1],h[2],h[3],h[4]
如果我們要求,3 - 4這的hash值,就等於 h[4] – h[3 - 1]*131^(4-3+1)
所以可以寫出題解:
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
using ULL = unsigned long long;
const int N = 1e6 + 5;
char s[N];
ULL h[N], p[N];

int m, base = 131;

ULL get(int l, int r){
    return h[r] - h[l - 1] * p[r - l + 1];//求出當前段的hash值
}

int main() {
    cin >> (s+1);
    p[0] = 1;
    int
n = strlen(s+1); for(int i = 1; i <= n; ++ i) { h[i] = h[i-1] * base + s[i] - 'a' + 1;//求出字首hash,先將小寫字元對映成數字 p[i] = p[i-1] * base;//求出base對應的冪 } cin >> m; while(m --) { int l1, r1, l2, r2; cin >> l1 >> r1 >> l2 >> r2; if(get(l1,r1) == get(l2,r2)) puts("Yes");//如果hash值相等就,相當於字串相等的 else puts("No"); } return 0; }