#include <bits/stdc++.h>
/**
* @brief
* b站视频:https://www.bilibili.com/video/BV1Ha411E7re?spm_id_from=333.337.search-card.all.click&vd_source=13dfbe5ed2deada83969fafa995ccff6
* 其他资料:https://oi-wiki.org/string/hash/
* /
using namespace std;
typedef unsigned long long ULL;
const int P = 131;
string str("abcdefghijklmn");
const ULL N = 100021;
ULL h[N], p[N];
int main()
{
/**
* @brief
* 字符串哈希;;
* 一个字符串的哈希值是前缀和, 字串是区间和;
*
* CRASH: 字符串不一样,但是Hash函数值一样,称为“哈希碰撞”;
* SOLVE: 巧妙设置p 和 M值,保证p和M互质;
* p 通常取 131 || 13331;
* M 通常区 2^64; h定义为ULL(unsigned long long);;;; 超过自动取模;
*
*/
// Hash Init
h[0] = 0; p[0] = 1;
for(int i = 1; i < str.size(); ++i) {
p[i] = p[i-1]*P;
h[i] = h[i-1]*P + str[i];
}
for(int i = 0; i < str.size(); ++i) {
cout<<h[i]<<" ";
}
// 区间和;;
// h[left, right] = h[right] - h[left - 1] *p[right - left + 1] ~~~`p[elem] 为字串的长度;
// Find:
ULL Sab = h[2] - h[0]*p[3];
cout<<Sab;
string str2("abcde");
ULL sb[N];
sb[0] = 0;
for(int i = 1; i < str2.size(); ++i) {
sb[i] = sb[i-1]*P + str2[i];
}
cout<<endl;
if(sb[3] == h[3]) {
cout<<"YES";
} else {
cout<<sb[3]<<" "<<h[3];
}
return 0;
}