結果
問題 | No.2761 Substitute and Search |
ユーザー | naut3 |
提出日時 | 2024-05-17 22:58:47 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 3,186 ms / 4,000 ms |
コード長 | 5,011 bytes |
コンパイル時間 | 14,887 ms |
コンパイル使用メモリ | 402,832 KB |
実行使用メモリ | 102,544 KB |
最終ジャッジ日時 | 2024-05-17 22:59:30 |
合計ジャッジ時間 | 34,143 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,812 KB |
testcase_01 | AC | 1 ms
6,944 KB |
testcase_02 | AC | 1 ms
6,940 KB |
testcase_03 | AC | 1 ms
6,944 KB |
testcase_04 | AC | 2,711 ms
102,544 KB |
testcase_05 | AC | 1,172 ms
91,264 KB |
testcase_06 | AC | 222 ms
91,136 KB |
testcase_07 | AC | 3,078 ms
96,996 KB |
testcase_08 | AC | 220 ms
91,264 KB |
testcase_09 | AC | 3,186 ms
97,056 KB |
testcase_10 | AC | 229 ms
91,264 KB |
testcase_11 | AC | 3,094 ms
97,092 KB |
testcase_12 | AC | 1,729 ms
94,180 KB |
testcase_13 | AC | 1,667 ms
94,196 KB |
testcase_14 | AC | 1,729 ms
94,208 KB |
testcase_15 | AC | 1,709 ms
94,292 KB |
コンパイルメッセージ
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 value pub 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); } }