AcWing 841. 字符串哈希
给定一个长度为n的字符串,再给定m个询问,每个询问包含四个整数l1,r1,l2,r2,请你判断[l1,r1]和[l2,r2
]这两个区间所包含的字符串子串是否完全相同。
字符串中只包含大小写英文字母和数字。
[输入格式]
第一行包含整数n和m,表示字符串长度和询问次数。
第二行包含一个长度为n的字符串,字符串中只包含大小写英文字母和数字。
接下来m行,每行包含四个整数l1,r1,l2,r2
,表示一次询问所涉及的两个区间。
注意,字符串的位置从1开始编号。
[输出格式]
对于每个询问输出一个结果,如果两个字符串子串完全相同则输出“Yes”,否则输出“No”。
每个结果占一行。
[数据范围]
1≤n,m≤105
输入样例:
8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2
输出样例:
Yes
No
Yes
如果ull类型的整数溢出了,就相当于取模2^64 了。 因为ull的范围是[0,2^64-1]。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=100005;
ull a[N],mi[N];
string s;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
cin>>s;
mi[0]=1; //注意开始权值为1
for(int i=1;i<=s.size();i++)
{
mi[i]=mi[i-1]*131; //计算每个位上的相应权值
//"131为经验值 即P=131或13331时 哈希冲突的可能性最小"
a[i]=a[i-1]*131+s[i-1]; //前缀和
}
while(m--)
{
int l,r,x,y;
scanf("%d%d%d%d",&l,&r,&x,&y);
int ll=r-l+1;
ull num=a[r]-a[l-1]*mi[ll];
ull numm=a[y]-a[x-1]*mi[ll];
//这步相当于将a[l-1]左移,使得a[l-1]的高位与a[r]对齐,计算
//如果看做十进制数就相当于在12345中提取2345,将12345减去1的幂的4次方
if(numm==num)puts("Yes");
else puts("No");
}
return 0;
}