【Hash 匹配】 兔子与兔子

传送门

题意

给定一个字符串\(S\)\(S\)仅包含小写英文字母,\(m\)个询问
每个询问包含两个区间\((l_{1},r_{1})\)\((l_{2},r_{2})\),问字符串中这两个区间的字符是否相等

数据范围

\(1 \leq \text { length }(S), m \leq 1000000\)

题解

  • 求初始每个下标的\(hash\)

  • 具体\(hash\)时候,假设有一个字符串\(abcde\),询问\((2,4)\)\(bcd\)\(hash\)

    • 整个字符串的\(hash\)值为\(12345\)

    • 此处的\(l=2,r=4\) ,所以可以求\(hash(l-1) = 1,hash(r) = 1234\)

    • \(hash(l\sim r) =hash(r) - hash(l-1) \times P^{3} = 234\)

  • 每次询问 \((l,r)\) 时通过相减求得即可

  • 预处理数组\(p\),记录\(p\)的各个次方

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ll long long
const int N=1e6+10,P=131;
typedef unsigned long long ull;

char str[N];
int m;
ull h[N],p[N];
int main()
{
    close;
    cin>>str+1;
    cin>>m;
    p[0]=1;
    int n=strlen(str+1);
    rep(i,1,n+1)
    {
         h[i]=h[i-1]*P+(str[i]-'a'+1);
         p[i]=p[i-1]*P;
    }
    while(m--)
    {
        int l1,r1,l2,r2;
        cin>>l1>>r1>>l2>>r2;
        if(h[r1] - (h[l1-1] * p[r1-l1+1]) == h[r2] - (h[l2-1] * p[r2-l2+1]))
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
}
posted @ 2020-09-24 11:27  Hyx'  阅读(127)  评论(0)    收藏  举报