字符串哈希

方法#

通常采用多项式 Hash 的方法,也就是说将字符串看做一个 b 进制的数。

进制数选择(大于所有字符对应的数字的最大值,且为质数),如:131 233 13331 19260817 等。

模数选择(双109的模数或者直接自然溢出):19260817 19660813 等。

然后就可以愉快的哈希了!

code(自然溢出)
Copy
ull hashh (string s) { ull res = 0; for (int i = s.size () - 1; i >= 0; i --) { res = (base * res + (s[i] - 'a')); } return res; }

子串哈希#

如何得到子串的哈希值呢?

可以先对字符串的每个前缀进行预处理,根据哈希方法:

定义字符串前缀的哈希值为 pi=s1×bi1+s2×bi2++si

那么子串 slr 的哈希值就为 plr=prpl1×brl+1

这里的 brl+1 可以通过预处理然后 O(1) 查询,也可以直接快速幂
O(logn) 搞定。

code
Copy
void hashh (string s) { h[0] = s[0] - 'a' + 1; for (int i = 1; i < s.size(); i ++) { h[i] = h[i - 1] * base + s[i] - 'a' + 1; } } cin >> l >> r; cout << h[r] - h[l - 1] * qpow (base, r - l + 1);

可以应用到字符串匹配。


最长回文子串#

采用二分答案,预处理正串的哈希值和反串的哈希值,枚举对称轴即可。

P3805模板
Copy
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int N = 11000007; const int base = 233; ull h1[N], h2[N], pw[N]; char s[N]; ull g1 (int l, int r) { return h1[r] - h1[l - 1] * pw[r - l + 1]; } ull g2 (int l, int r) { return h2[r] - h2[l - 1] * pw[r - l + 1]; } int main () { scanf ("%s", s + 1); int len = strlen (s + 1); h1[0] = h2[len + 1] = 0; pw[0] = 1; for (int i = 1; i <= len; i ++) { h1[i] = h1[i - 1] * base + s[i] - 'a' + 1; } int l = 1, r = len; while (l <= r) { int c1 = s[l], d1 = s[r]; s[l] = d1, s[r] = c1; l ++, r --; } for (int i = 1; i <= len; i ++) { h2[i] = h2[i - 1] * base + s[i] - 'a' + 1; } l = 1, r = len; while (l <= r) { int c1 = s[l], d1 = s[r]; s[l] = d1, s[r] = c1; l ++, r --; } for (int i = 1; i <= len; i ++) { pw[i] = pw[i - 1] * base; } int ans = 1; for (int i = 1; i <= len; i ++) { int la = 1, ra = min (i - 1, len - i), t = 0; while (la <= ra) { int mid = (la + ra) >> 1, ll = i - mid, rr = i + mid; if (g1 (ll, rr) == g2 (len - rr + 1, len - ll + 1)) { la = mid + 1; ans = max (ans, mid * 2 + 1); } else { ra = mid - 1; } } t = 0; int lb = 0, rb = min (i - 1, len - i - 1); while (lb <= rb) { int mid = (lb + rb) >> 1, ll = i - mid, rr = i + mid + 1; if (g1 (ll, rr) == g2 (len - rr + 1, len - ll + 1)) { lb = mid + 1; ans = max (ans, mid * 2 + 2); } else { rb = mid - 1; } } } cout << ans << endl; return 0; }

最长公共子串#

预处理每个字符串长度为 x 的哈希值放入哈希表。

易得长度 k 可以二分答案,所以可以解决。

posted @   21_devoted  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示
CONTENTS