C++字符串hash

字符串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;
}
相关推荐
大江东去浪淘尽千古风流人物33 分钟前
【VLN】VLN(Vision-and-Language Navigation视觉语言导航)算法本质,范式难点及解决方向(1)
人工智能·python·算法
rainbow68891 小时前
Linux文件描述符与重定向原理
c++
努力学算法的蒟蒻1 小时前
day79(2.7)——leetcode面试经典150
算法·leetcode·职场和发展
2401_841495641 小时前
【LeetCode刷题】二叉树的层序遍历
数据结构·python·算法·leetcode·二叉树··队列
AC赳赳老秦1 小时前
2026国产算力新周期:DeepSeek实战适配英伟达H200,引领大模型训练效率跃升
大数据·前端·人工智能·算法·tidb·memcache·deepseek
CodeSheep程序羊2 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展
2401_841495642 小时前
【LeetCode刷题】二叉树的直径
数据结构·python·算法·leetcode·二叉树··递归
budingxiaomoli2 小时前
优选算法-字符串
算法
编程小白20262 小时前
从 C++ 基础到效率翻倍:Qt 开发环境搭建与Windows 神级快捷键指南
开发语言·c++·windows·qt·学习
qq7422349842 小时前
APS系统与OR-Tools完全指南:智能排产与优化算法实战解析
人工智能·算法·工业·aps·排程