P10468 兔子与兔子
审题
给定一个字符串,求该字符串的两个子串是否一样。
方法
【暴力】对于一个字符串,我们将它的两个子串截取出来,再判断是否一样。由于判断的时间复杂度为
【字符串哈希】可以发现判断字符串一样的复杂度可以通过字符串哈希优化为
思路
首先求出字符串的前缀哈希值。通过以下代码实现:
for(int i = 1;i < s.size();i++){
hs[i] = hs[i - 1] * 113 + s[i];
pw[i] = pw[i - 1] * 113;
}
这边推荐使用质数作为进制数,这样可以更加避免哈希冲突。
然后我们将所求划分为一个子问题,即在区间中子串的哈希值是否相等。我们举一个例子:例如
代码
#include<bits/stdc++.h>
using namespace std;
string s;
int q;
unsigned long long hs[1000005];
unsigned long long pw[1000005];
unsigned long long get_sizeHash(int a,int b){ //区间中子串的哈希值
return hs[b] - hs[a - 1] * pw[b - a + 1];
}
int main(){
cin >> s;
s = " " + s;
pw[0] = 1; //次方的初始化
for(int i = 1;i < s.size();i++){
hs[i] = hs[i - 1] * 113 + s[i]; //前缀哈希值
pw[i] = pw[i - 1] * 113; //113的次方
}
cin >> q;
while(q--){
int a,b,x,y;
cin >> a >> b >> x >> y;
if(get_sizeHash(a,b) == get_sizeHash(x,y)) cout << "Yes\n"; //判断两个区间中子串的哈希值是否相等
else cout << "No\n";
}
return 0;
}
不抄题解,从我做起!