字符串哈希
Rabin Karp
基于 Rabin Karp 算法的字符串子串哈希值计算
TypeScript
export function useStrHash(s: string, b = 1337, mod = 1e9 + 7) {
const n = s.length
const $ = BigInt
const bb: number[] = new Array(n + 1).fill(0)
const h: number[] = new Array(n + 1).fill(0)
bb[0] = 1
for (let i = 0; i < n; i++) {
const val = s[i].charCodeAt(0)
bb[i + 1] = (bb[i] * b) % mod
h[i + 1] = (h[i] * b + val) % mod
}
// [l, r) 包含 l 不包含 r
return (l: number, r: number) => {
if (h[l] * bb[r - l] > Number.MAX_SAFE_INTEGER)
return (
(Number($(h[r]) - (($(h[l]) * $(bb[r - l])) % $(mod))) + mod) %
mod
)
return (h[r] - ((h[l] * bb[r - l]) % mod) + mod) % mod
}
}
JavaScript
export function useStrHash(s, b = 1337, mod = 1e9 + 7) {
const n = s.length
const $ = BigInt
const bb = new Array(n + 1).fill(0)
const h = new Array(n + 1).fill(0)
bb[0] = 1
for (let i = 0; i < n; i++) {
const val = s[i].charCodeAt(0)
bb[i + 1] = (bb[i] * b) % mod
h[i + 1] = (h[i] * b + val) % mod
}
return (l, r) => {
if (h[l] * bb[r - l] > Number.MAX_SAFE_INTEGER)
return (
(Number($(h[r]) - (($(h[l]) * $(bb[r - l])) % $(mod))) + mod) %
mod
)
return (h[r] - ((h[l] * bb[r - l]) % mod) + mod) % mod
}
}
Rust
use std::ops::{Bound, RangeBounds};
pub struct StrHash {
hash: Vec<u64>,
pow: Vec<u64>,
}
impl StrHash {
const MOD: u64 = 1e9 as u64 + 7;
const BASE: u64 = 1337;
pub fn from_str(s: &str) -> Self {
let s = s.as_bytes();
let n = s.len();
let mut hash = vec![0; n + 1];
let mut pow = vec![0; n + 1];
pow[0] = 1;
for i in 0..n {
hash[i + 1] = (hash[i] * Self::BASE + s[i] as u64) % Self::MOD;
pow[i + 1] = pow[i] * Self::BASE % Self::MOD;
}
Self { hash, pow }
}
pub fn get<R: RangeBounds<usize>>(&self, range: R) -> u64 {
let start = match range.start_bound() {
Bound::Included(&s) => s,
Bound::Excluded(&s) => s + 1,
_ => 0,
};
let end = match range.end_bound() {
Bound::Included(&e) => e + 1,
Bound::Excluded(&e) => e,
_ => self.hash.len() - 1,
};
let hl = self.hash[start];
let hr = self.hash[end];
let pow_len = self.pow[end - start];
(hr + Self::MOD - (hl * pow_len) % Self::MOD) % Self::MOD
}
}
Java
public class StringHash {
private final long[] hash;
private final long[] pow;
private final int b = 1337;
private final int mod = 1000000007;
public StringHash(String s) {
int n = s.length();
hash = new long[n + 1];
pow = new long[n + 1];
pow[0] = 1;
for (int i = 0; i < n; i++) {
hash[i + 1] = (hash[i] * b + s.charAt(i)) % mod;
pow[i + 1] = pow[i] * b % mod;
}
}
public long hash(int i, int j) {
return (hash[j] - hash[i] * pow[j - i] % mod + mod) % mod;
}
}