字符串hash,对应蓝桥云课 子串的比较 代码框架见下
cpp
/*
hash(0,0) = s[0]
hash(0,1) = s[0] * B + s[1]
hash(0,2) = s[0] * B^2 + s[1] * B + s[0]
hash(0,r) = sum(s[i] * B^(r - i) | 0 <= i <= r);
hash(0, l-1) = sum(s[i] * B^(l-1-i) | 0 <= i <= l-1)
hash(0, l-1) = sum(s[i] * B^(l-i-1) | 0 <= i <= l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) | 0 <= i <= l-1)
hash(0, r) - hash(0, l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) |0 <= i <= r) - sum(s[i] * B^(r-i) | 0 <= i <= l-1)
= sum(s[i] * B^(r-i) | 0 <= i <= r)
*/
#include <iostream>
using namespace std;
#define maxn 1000010
#define ull unsigned long long
#define B 271
ull Power[maxn];
ull Hash[maxn];
void init(const string& s){
Power[0] = 1;
Hash[0] = s[0];
for(int i=1; i<s.size(); ++i){
Hash[i] = Hash[i-1]*B + s[i];
Power[i] = Power[i-1] * B;
}
}
ull get(int l, int r){
if(l == 0){
return Hash[r];
}
return Hash[r] - Hash[l-1] * Power[r - l + 1];
}
int main()
{
string s;
cin >> s;
init(s);
int q;
cin >> q;
while(q--){
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
if(get(l1, r1) == get(l2, r2)){
cout << "Yes" << endl;
}else{
cout << "No" << endl;
}
}
// 请在此输入您的代码
return 0;
}
代码练习 1 对应蓝桥云课 斤斤计较的小Z 代码见下
cpp
/*
hash(0,0) = s[0]
hash(0,1) = s[0] * B + s[1]
hash(0,2) = s[0] * B^2 + s[1] * B + s[0]
hash(0,r) = sum(s[i] * B^(r - i) | 0 <= i <= r);
hash(0, l-1) = sum(s[i] * B^(l-1-i) | 0 <= i <= l-1)
hash(0, l-1) = sum(s[i] * B^(l-i-1) | 0 <= i <= l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) | 0 <= i <= l-1)
hash(0, r) - hash(0, l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) |0 <= i <= r) - sum(s[i] * B^(r-i) | 0 <= i <= l-1)
= sum(s[i] * B^(r-i) | 0 <= i <= r)
*/
#include <iostream>
using namespace std;
#define maxn 1000010
#define ull unsigned long long
#define B 271
ull Power[maxn];
ull Hash[maxn];
void init(const string& s){
Power[0] = 1;
Hash[0] = s[0];
for(int i=1; i<s.size(); ++i){
Hash[i] = Hash[i-1]*B + s[i];
Power[i] = Power[i-1] * B;
}
}
ull get(int l, int r){
if(l == 0){
return Hash[r];
}
return Hash[r] - Hash[l-1] * Power[r - l + 1];
}
int main()
{
string a, b;
cin >> a >> b;
init(a);
ull v = get(0, a.size()-1);
int len = a.size();
int ans = 0;
init(b);
for(int i=0; i + len - 1 < b.size(); ++i){
if(get(i, i+len-1) == v){
++ans;
}
}
cout << ans << endl;
return 0;
}
代码练习2 对应蓝桥云课 小蓝的开机密码 代码见下
cpp
/*
hash(0,0) = s[0]
hash(0,1) = s[0] * B + s[1]
hash(0,2) = s[0] * B^2 + s[1] * B + s[0]
hash(0,r) = sum(s[i] * B^(r - i) | 0 <= i <= r);
hash(0, l-1) = sum(s[i] * B^(l-1-i) | 0 <= i <= l-1)
hash(0, l-1) = sum(s[i] * B^(l-i-1) | 0 <= i <= l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) | 0 <= i <= l-1)
hash(0, r) - hash(0, l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) |0 <= i <= r) - sum(s[i] * B^(r-i) | 0 <= i <= l-1)
= sum(s[i] * B^(r-i) | 0 <= i <= r)
*/
#include <iostream>
using namespace std;
#define maxn 1000010
#define ull unsigned long long
#define B 271
ull Power[maxn];
ull Hash[maxn];
void init(const string& s){
Power[0] = 1;
Hash[0] = s[0];
for(int i=1; i<s.size(); ++i){
Hash[i] = Hash[i-1]*B + s[i];
Power[i] = Power[i-1] * B;
}
}
ull get(int l, int r){
if(l == 0){
return Hash[r];
}
return Hash[r] - Hash[l-1] * Power[r - l + 1];
}
int main()
{
string s;
cin >> s;
int n = s.size();
init(s);
int ans = 0;
//1 逆序枚举满足条件的长度,如果发现有一个长度满足需求,则直接跳出
int l = -1, r = n/2 + 1;
while(l+1 < r){
int i = (l + r) / 2;
bool check = false;
for(int j=0; j+2*i-1 < n; ++j){
int L = j;
int R = j + i - 1;
ull v = get(L, R);
for(int k = R+1; k + i - 1 < n; ++k){
if(v == get(k, k+i-1)){
check = true;
break;
}
}
if(check) break;
}
if(check){
l = i;
}else{
r = i;
}
}
cout << l << endl;
// 请在此输入您的代码
return 0;
}
代码练习3 对应蓝桥云课 小蓝的神秘日记 代码见下
cpp
/*
hash(0,0) = s[0]
hash(0,1) = s[0] * B + s[1]
hash(0,2) = s[0] * B^2 + s[1] * B + s[0]
hash(0,r) = sum(s[i] * B^(r - i) | 0 <= i <= r);
hash(0, l-1) = sum(s[i] * B^(l-1-i) | 0 <= i <= l-1)
hash(0, l-1) = sum(s[i] * B^(l-i-1) | 0 <= i <= l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) | 0 <= i <= l-1)
hash(0, r) - hash(0, l-1) * B^{r - l + 1}
= sum(s[i] * B^(r-i) |0 <= i <= r) - sum(s[i] * B^(r-i) | 0 <= i <= l-1)
= sum(s[i] * B^(r-i) | 0 <= i <= r)
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 1000010
#define ull unsigned long long
#define B 271
ull Power[maxn];
ull Hash[maxn];
void init(const string& s){
Power[0] = 1;
Hash[0] = s[0];
for(int i=1; i<s.size(); ++i){
Hash[i] = Hash[i-1]*B + s[i];
Power[i] = Power[i-1] * B;
}
}
ull get(int l, int r){
if(l == 0){
return Hash[r];
}
return Hash[r] - Hash[l-1] * Power[r - l + 1];
}
int n;
struct Pair{
ull val;
int pos;
};
bool cmp(const Pair& a, const Pair& b){
if(a.val == b.val){
return a.pos < b.pos;
}
return a.val < b.val;
}
bool check(int len){
vector<Pair> v;
// 1 获取所有长度为len的子串哈希值
for(int i=0; i+len-1<n; ++i){
ull val = get(i, i+len-1);
v.push_back({val, i});
}
// 2 把所有子串的哈希值相等的元素排在一起,并且按位置递增排序
sort(v.begin(), v.end(), cmp);
// 3 找到所有子串哈希值相等的元素,判断位置是否重叠,如果一旦发现不重叠,返回true
for(int i=0; i<v.size(); ++i){
int j = i+1;
for(; j < v.size(); ++j){
if(v[j].val != v[i].val){
i = j - 1;
break;
}
if(v[j].pos - v[i].pos >= len){
return true;
}
}
}
// 如果找不到,则返回false
return false;
}
int main()
{
string s;
cin >> s;
n = s.size();
init(s);
//1 逆序枚举满足条件的长度,如果发现有一个长度满足需求,则直接跳出
int l = -1, r = n/2 + 1;
while(l+1 < r){
int mid = (l + r) / 2;
if(check(mid)){
l = mid;
}else{
r = mid;
}
}
cout << l << endl;
// 请在此输入您的代码
return 0;
}