Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 376 Solved: 75
[Submit][Status][Web Board]
Description
很久很久以前,森林里住着一群兔子。
有一天,兔子们想要研究自己的DNA序列。
我们首先选取一个好长好长的DNA序列(小兔子是外星生物,DNA序列可能包含26个小写英文字母)。
然后我们每次选择两个区间,询问如果用两个区间里的DNA序列分别生产出来两只兔子,这两个兔子是否一模一样。
注意两个兔子一模一样只可能是他们的DNA序列一模一样。
Input
第一行输入一个DNA字符串S。
第二行一个数字m,表示m次询问。
接下来m行,每行四个数字l1,r1,l2,r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
数据范围
1≤length(S),m≤1000000
Output
对于每次询问,输出一行表示结果。
如果两只兔子完全相同输出Yes,否则输出No(注意大小写)。
Sample Input
aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2
Sample Output
Yes
No
Yes
HINT
双hash+快读,双hash是预防精心构造的数据的。
代码:
#include<bits/stdc++.h>
using namespace std;
int mod1=998244,base1=233,n,T,ll=1;
char s[1000001];
int mod2=666623,base2=431;
long long h2[1000001],P2[1000001],h1[1000001],P1[1000001];
void read(int &x) {
char ch;
bool ok;
for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') ok=1;
for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
if(ok) x=-x;
}
void build1()
{
for(int i=1;i<=n;i++)
h1[i]=ll*h1[i-1]*base1%mod1+s[i]-'a';
P1[0]=1;
for(int i=1;i<=n;i++)
P1[i]=ll*P1[i-1]*base1%mod1;
}
bool check1(int l1,int r1,int l2,int r2)
{
int len=r1-l1+1;
int h11=((h1[r1]-ll*h1[l1-1]*P1[len]%mod1)+mod1)%mod1;
int h12=((h1[r2]-ll*h1[l2-1]*P1[len]%mod1)+mod1)%mod1;
return h11==h12;
}
void build2()
{
for(int i=1;i<=n;i++)
h2[i]=ll*h2[i-1]*base2%mod2+s[i]-'a';
P2[0]=1;
for(int i=1;i<=n;i++)
P2[i]=ll*P2[i-1]*base2%mod2;
}
bool check2(int l1,int r1,int l2,int r2)
{
int len=r1-l1+1;
int h21=((h2[r1]-ll*h2[l1-1]*P2[len]%mod2)+mod2)%mod2;
int h22=((h2[r2]-ll*h2[l2-1]*P2[len]%mod2)+mod2)%mod2;
return h21==h22;
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
build1();
build2();
read(T);
while(T--)
{
int l1,r1,l2,r2;
read(l1);
read(r1);
read(l2);
read(r2);
if(r1-l1+1!=r2-l2+1)
puts("No");
else
puts((check1(l1,r1,l2,r2)&&check2(l1,r1,l2,r2))?"Yes":"No");
}
return 0;
}