use std::collections::VecDeque; use std::io::{self, BufRead}; const B: u64 = 30; const H: u64 = 9007199254740997; struct SegmentTree { size: usize, pow_b: Vec, array: Vec, weights: Vec, l_queue: VecDeque, r_queue: VecDeque, } impl SegmentTree { fn new(init_array: &[u64], pow_b: &[u64]) -> Self { let mut n = 1; while n < init_array.len() { n *= 2; } let size = n; let mut array = vec![0; 2 * size]; let mut weights = vec![0; 2 * size]; for (i, &a) in init_array.iter().enumerate() { array[size + i] = a; weights[size + i] = 1; } let mut start_index = size / 2; let mut end_index = size; while start_index >= 1 { for i in start_index..end_index { weights[i] = weights[2 * i] + weights[2 * i + 1]; array[i] = Self::op(&array, &pow_b, &weights, 2 * i, 2 * i + 1); } end_index = start_index; start_index /= 2; } Self { size, pow_b: pow_b.to_vec(), array, weights, l_queue: VecDeque::new(), r_queue: VecDeque::new(), } } fn op(array: &[u64], pow_b: &[u64], weights: &[u64], l: usize, r: usize) -> u64 { let mut a = (pow_b[weights[r] as usize] * array[l]) % H; a = (a + array[r]) % H; a } fn set(&mut self, x: usize, a: u64) { let mut index = self.size + x; self.array[index] = a; while index > 1 { index /= 2; self.array[index] = Self::op(&self.array, &self.pow_b, &self.weights, 2 * index, 2 * index + 1); } } fn get_sum(&mut self, mut l: usize, mut r: usize) -> u64 { let mut s = 0; let mut L = self.size + l; let mut R = self.size + r; while L < R { if R & 1 == 1 { R -= 1; self.r_queue.push_front(R); } if L & 1 == 1 { self.l_queue.push_back(L); L += 1; } L /= 2; R /= 2; } while let Some(l) = self.l_queue.pop_front() { s = (s * self.pow_b[self.weights[l] as usize]) % H; s = (s + self.array[l]) % H; } while let Some(l) = self.r_queue.pop_front() { s = (s * self.pow_b[self.weights[l] as usize]) % H; s = (s + self.array[l]) % H; } s } } fn main() { let stdin = io::stdin(); let mut lines = stdin.lock().lines(); let first_line = lines.next().unwrap().unwrap(); let mut iter = first_line.split_whitespace().map(|s| s.parse::().unwrap()); let (n, l, q) = (iter.next().unwrap(), iter.next().unwrap(), iter.next().unwrap()); let mut s_arrays = Vec::new(); let mut segs = Vec::new(); let mut pow_b = vec![0; l + 1]; let mut b = 1; for i in 0..=l { pow_b[i] = b; b = (b * B) % H; } for _ in 0..n { let s = lines.next().unwrap().unwrap(); let s_array: Vec = s.chars().map(|c| (c as u64) - ('a' as u64) + 1).collect(); s_arrays.push(s_array.clone()); segs.push(SegmentTree::new(&s_array, &pow_b)); } for _ in 0..q { let query = lines.next().unwrap().unwrap(); let values: Vec<&str> = query.split_whitespace().collect(); if values[0] == "1" { let k = values[1].parse::().unwrap() - 1; let c = (values[2].chars().next().unwrap() as u64) - ('a' as u64) + 1; let d = (values[3].chars().next().unwrap() as u64) - ('a' as u64) + 1; for i in 0..n { if s_arrays[i][k] == c { s_arrays[i][k] = d; segs[i].set(k, d); } } } else if values[0] == "2" { let t = values[1]; let mut t_hash = 0; for t0 in t.chars() { t_hash = (t_hash * B) % H; t_hash = (t_hash + (t0 as u64 - 'a' as u64 + 1)) % H; } let t_len = t.len(); let mut answer = 0; for i in 0..n { let x = segs[i].get_sum(0, t_len); if t_hash == x { answer += 1; } } println!("{}", answer); } } }