核心就是把字符串理解成一个P进制数字(当成整数模拟一下快速理解!!!)
代码中的p进制为base = 131, 或者13331. MOD取大整数,这里可以偷懒用ULL,溢出会自动取模,这样可以大大减少哈希碰撞的概率,有时候还会用双哈希来减少碰撞的概率。
比如字符串abc,就看成$a*p^2+b*p^1+c*p^0$,剩下的当成整数来模拟就可以了
#include <iostream>
using namespace std;
constexpr int base = 131, N = 1e5;
typedef unsigned long long ULL;
ULL p[N+50], h[N+50];
int n, m;
string s;
//计算[l,r]的哈希值
ULL gethash(int l, int r) {
return h[r] - h[l-1] * p[r-l+1];
}
//预处理哈希值和p进制
void init() {
p[0] = 1;//不要忘记p进制的0次方为1
h[0] = 0;
for(int i = 1; i <= n; ++i) {
p[i] = p[i-1] * base;
h[i] = h[i-1] * base + s[i];
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cin >> n >> m;
cin >> s;
s = ' ' + s;//让字符串变成下表从1开始,好处理好理解
init();
for(; m--;) {
int l, r, L, R;
cin >> l >> r >> L >> R;
if(gethash(l, r) == gethash(L, R)) {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
return 0;
}