結果
問題 | No.2761 Substitute and Search |
ユーザー |
![]() |
提出日時 | 2024-05-17 22:58:47 |
言語 | Rust (1.83.0 + proconio) |
結果 |
AC
|
実行時間 | 3,420 ms / 4,000 ms |
コード長 | 5,011 bytes |
コンパイル時間 | 13,816 ms |
コンパイル使用メモリ | 401,776 KB |
実行使用メモリ | 102,572 KB |
最終ジャッジ日時 | 2024-12-20 14:59:59 |
合計ジャッジ時間 | 38,533 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 13 |
コンパイルメッセージ
warning: unused variable: `L` --> src/main.rs:7:19 | 7 | N: usize, L: usize, Q: usize, | ^ help: if this is intentional, prefix it with an underscore: `_L` | = note: `#[warn(unused_variables)]` on by default
ソースコード
#![allow(non_snake_case, unused_imports)]use proconio::{fastout, input, marker::*};#[fastout]fn main() {input! {N: usize, L: usize, Q: usize,mut S: [Chars; N],}let mut rhs = vec![];for i in 0..N {let rh = UpdateableRollingHash::from(&S[i]);rhs.push(rh);}for _ in 0..Q {input! {t: usize}if t == 1 {input! {k: Usize1, c: char, d: char,}for i in 0..N {if S[i][k] == c {S[i][k] = d;rhs[i].update(k, d);}}} else {input! {t: Chars,}let l = t.len();let rh = UpdateableRollingHash::from(&t);let h = rh.hash(0..l);let mut ans = 0usize;for i in 0..N {let hi = rhs[i].hash(0..l);if hi == h {ans += 1;}}println!("{}", ans);}}}pub struct UpdateableRollingHash {length: usize,tree: Vec<u64>,pow: Vec<u64>,}impl UpdateableRollingHash {const MOD: u64 = (1_u64 << 61) - 1;const MASK_30: u64 = (1_u64 << 30) - 1;const MASK_31: u64 = (1_u64 << 31) - 1;const MASK_61: u64 = (1_u64 << 61) - 1;const BASE: u64 = 100;const STR_BASE: char = 'a';fn inv(x: u64) -> u64 {return Self::pow(x, Self::MOD - 2);}fn pow(mut a: u64, mut b: u64) -> u64 {let mut ret = 1;while b > 0 {if b & 1 == 1 {ret = Self::cmod(Self::mul(ret, a));}a = Self::cmod(Self::mul(a, a));b >>= 1;}return ret;}fn mul(a: u64, b: u64) -> u64 {let au = a >> 31;let ad = a & Self::MASK_31;let bu = b >> 31;let bd = b & Self::MASK_31;let mid = ad * bu + au * bd;let midu = mid >> 30;let midd = mid & Self::MASK_30;return Self::cmod(au * bu * 2 + midu + (midd << 31) + ad * bd);}fn cmod(x: u64) -> u64 {let xu = x >> 61;let xd = x & Self::MASK_61;let ret = xu + xd;if ret >= Self::MOD {return ret - Self::MOD;} else {return ret;}}/// Prepare to calc given string s's substring hash valuepub fn from(s: &[char]) -> Self {let length = s.len();let mut tree = vec![0; 2 * length];let mut pow = vec![1];for i in 0..length {pow.push(Self::cmod(Self::mul(pow[i], Self::BASE)));}for i in 0..length {tree[i + length] = Self::cmod(Self::mul(s[i] as u64 + 1 - Self::STR_BASE as u64,pow[length - i - 1],));}for i in (1..length).rev() {tree[i] = Self::cmod(tree[i << 1] + tree[(i << 1) | 1]);}return Self {length: length,tree: tree,pow: pow,};}/// Update p-th character to 'c'pub fn update(&mut self, mut p: usize, c: char) {let v = Self::cmod(Self::mul(c as u64 + 1 - Self::STR_BASE as u64,self.pow[self.length - p - 1],));p += self.length;self.tree[p] = v;while p > 1 {p >>= 1;self.tree[p] = Self::cmod(self.tree[p << 1] + self.tree[(p << 1) | 1]);}}fn _get_sum(&self, left: usize, right: usize) -> u64 {let (mut l, mut r) = (left + self.length, right + self.length);let (mut vl, mut vr) = (0, 0);while l < r {if l & 1 == 1 {vl = Self::cmod(vl + self.tree[l]);l += 1;}if r & 1 == 1 {r -= 1;vr = Self::cmod(self.tree[r] + vr);}l >>= 1;r >>= 1;}return Self::cmod(vl + vr);}fn _hash(&self, left: usize, right: usize) -> u64 {let lv = self._get_sum(0, left);let rv = self._get_sum(0, right);return Self::cmod(Self::mul(rv + Self::MOD * 4 - lv,Self::inv(self.pow[self.length - right + 1]),));}/// Calculate hash value of s[range]pub fn hash<R: std::ops::RangeBounds<usize>>(&self, range: R) -> u64 {let left = match range.start_bound() {std::ops::Bound::Included(&l) => l,std::ops::Bound::Excluded(&l) => l + 1,std::ops::Bound::Unbounded => 0,};let right = match range.end_bound() {std::ops::Bound::Included(&r) => r + 1,std::ops::Bound::Excluded(&r) => r,std::ops::Bound::Unbounded => self.length - 1,};return self._hash(left, right);}}