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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
//! ローリングハッシュに関する wrapper クラス。
use super::super::traits::binop;
use std::fmt::Debug;
use binop::{Associative, Identity, Magma};
/// 文字列連結をローリングハッシュで行う演算を持つ。
///
/// # Examples
/// ```
/// use nekolib::traits::Magma;
/// use nekolib::utils::OpRollHash;
///
/// let op_rh = OpRollHash::<998244353>::default();
/// let value_of = |s| op_rh.value_of(s);
/// let op = |x, y| op_rh.op(x, y);
///
/// let abr = value_of("abr");
/// let a = value_of("a");
/// let abra = value_of("abra");
/// assert_eq!(op(abr, a), abra);
///
/// let s = "abracadabra";
/// assert_eq!(value_of(&s[0..4]), abra);
/// assert_eq!(value_of(&s[7..11]), abra);
/// assert_ne!(value_of(&s[1..5]), abra);
/// assert_eq!(value_of(s), op(op(abra, value_of("cad")), abra));
/// ```
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum OpRollHash<const B: u64> {
OpRollHashV,
}
pub use OpRollHash::OpRollHashV;
impl<const B: u64> Default for OpRollHash<B> {
fn default() -> Self { OpRollHashV }
}
impl<const B: u64> Magma for OpRollHash<B> {
type Set = (u64, u64);
fn op(&self, (hx, lx): Self::Set, (hy, ly): Self::Set) -> Self::Set {
((hx * ly + hy) % B, (lx * ly) % B)
}
}
impl<const B: u64> Identity for OpRollHash<B> {
fn id(&self) -> Self::Set { (0, 1) }
}
impl<const B: u64> Associative for OpRollHash<B> {}
impl<const B: u64> OpRollHash<B> {
#[must_use]
pub fn value_of(&self, s: &str) -> <Self as Magma>::Set {
s.chars().fold((0, 0), |acc, x| self.op(acc, (x as u64, B)))
}
}