持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情
AcWing:841. 字符串哈希
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≤10^5
输入样例:
8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2
输出样例:
Yes
No
Yes
问题解析
首先我们可以想一想,为什么一个十进制数是独一无二的?
比如对于123来说,因为满足百位数是1,十位数是2,个数为是3的三位数就只有123一个了。
对于同一进制来说,只要各个位的数字是固定的,那么最后得到的数就肯定是同一个。
字符串哈希其实就是把字符串转化成一个base进制下的数,我们判断两个数一不一样就是看他们大小是否相等,那么对应的,如果两个字符串转化成的数相等,就能说明这两个字符串是一样的。
AC代码
#include<iostream>
using namespace std;
#include<vector>
typedef unsigned long long ull;
int n,m,p=99971,base=13331;
ull get_hash(vector<ull>&v,int l,int r,vector<ull>&bpow)
{
ull t=v[l-1]*bpow[r-l+1];
return (v[r]-t);
}
int main()
{
cin>>n>>m;
string str;
cin>>str;
vector<ull>v(n+1),bpow(n+1,1);
ull res=0;
for(int i=1;i<=n;i++)
{
res=(res*base+str[i-1]);
v[i]=res;
bpow[i]=bpow[i-1]*base;
}
while(m--)
{
int l1,l2,r1,r2;
cin>>l1>>r1>>l2>>r2;
if(str[l1-1]!=str[l2-1]||str[r1-1]!=str[r2-1])
{
cout<<"No"<<endl;
continue;
}
ull x=get_hash(v,l1,r1,bpow);
ull y=get_hash(v,l2,r2,bpow);
if(x==y)
{
cout<<"Yes"<<'\n';
}
else cout<<"No"<<'\n';
}
return 0;
}