AcWing 138. 兔子與兔子【前綴哈希】

很久很久以前,森林裏住着一羣兔子。

有一天,兔子們想要研究自己的 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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章