字符串哈希又称,字符串的前缀哈希法
个人感觉比kmp算法适用性更强
又称,字符串的前缀哈希法
个人感觉比kmp算法适用性更强
算法思路
将一个字符串,转化为p进制的数,然后除留取余(散列函数)进行哈希映射。
例如上图中例①,将字符串ABCD转化为一个四进制的数,然后再modQ,最终将字符串映射到0∼Q−1。
注意事项:
- 不能将字符映射成
0
- 不考虑冲突的处理。
假定不会冲突???(可能冲突概率太小)
y总经验之谈:
一般情况下,设定
p=131或者p=13331
Q=264
99.99%不会产生冲突
利用前缀字符串的哈希值,来求任意子串的哈希值。
已知h[L−1]和h[R],如何求L∼R的哈希值?
核心公式:
h[L∼R]=h[R]−h[L−1]×pR−(L−1)
简单举例:
可以快速判断两个子字符是否相同(根据哈希值是否相同来判断)
字符串哈希-acwing 841
问题描述
给定一个长度为n的字符串,再给定m个询问,每个询问包含四个整数 l1,r1,l2,r2,请你判断 [l1,r1]和 [l2,r2]这两个区间所包含的字符串子串是否完全相同。
字符串中只包含大小写英文字母和数字。
注意,字符串的位置从1开始编号。
数据范围
1≤n,m≤105
完整代码
关于以下代码:
- 字符串哈希中推荐设定的Q=264,正好是
unsigned long long
类型变量的范围,因此这里在极大概率不会冲突的前提下,直接使用ULL
存储哈希值,如果冲突则溢出。 - 记住以下操作,要熟练。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <iostream> #include <algorithm>
using namespace std;
typedef unsigned long long ULL;
const int N = 100010, P = 131;
int n, m; char str[N]; ULL h[N], p[N];
ULL get(int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; }
int main() { scanf("%d%d", &n, &m); scanf("%s", str + 1); p[0] = 1; for (int i = 1; i <= n; i ++ ) { h[i] = h[i - 1] * P + str[i]; p[i] = p[i - 1] * P; }
while (m -- ) { int l1, r1, l2, r2; scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
if (get(l1, r1) == get(l2, r2)) puts("Yes"); else puts("No"); }
return 0; }
|