use proconio::{input, marker::{Chars, Usize1}}; use std::num::*; struct TrieNode { pub children: [Option; 26], pub sum: usize, } impl TrieNode { pub fn new() -> Self { Self { children: [None; 26], sum: 0, } } } struct Trie { nodes: Vec, subst: Vec>>, } impl Trie { pub fn new(l: usize) -> Self { Self { nodes: vec![TrieNode::new()], subst: vec![(0 .. 26).map(|i| vec![i] ).collect(); l], } } pub fn add(&mut self, s: &[usize]) { let mut cur = 0; self.nodes[cur].sum += 1; for k in 0 .. s.len() { let c = s[k]; if self.nodes[cur].children[c].is_none() { let id = self.nodes.len(); self.nodes.push(TrieNode::new()); self.nodes[cur].children[c] = NonZeroU32::new(id as u32); } cur = self.nodes[cur].children[c].unwrap().get() as usize; self.nodes[cur].sum += 1; } } pub fn substitute(&mut self, k: usize, c: usize, d: usize) { let mut src = std::mem::take(&mut self.subst[k][c]); self.subst[k][d].append(&mut src); } pub fn search(&mut self, s: &[usize]) -> usize { let mut cur = 0; for k in 0 .. s.len() { let d = s[k]; let mut next = None; for c in self.subst[k][d].clone() { if let Some(id) = self.nodes[cur].children[c as usize] { if let Some(next_id) = next { self.merge(next_id, id.get() as usize); self.nodes[cur].children[c as usize] = None; } else { next = Some(id.get() as usize); } } } if let Some(id) = next { cur = id; } else { return 0; } } self.nodes[cur].sum } fn merge(&mut self, dst: usize, src: usize) { self.nodes[dst].sum += self.nodes[src].sum; for c in 0 .. 26 { if let Some(src_child) = self.nodes[src].children[c] { if let Some(dst_child) = self.nodes[dst].children[c] { self.merge(dst_child.get() as usize, src_child.get() as usize); } else { self.nodes[dst].children[c] = Some(src_child); } } } } } fn convert(s: &[char]) -> Vec { s.iter().map(|&c| (c as u8 - b'a') as usize ).collect() } fn main() { input! { n: usize, l: usize, q: usize, strs: [Chars; n], } let mut trie = Trie::new(l); for s in strs { trie.add(&convert(&s)); } for _ in 0 .. q { input!(qtype: usize); if qtype == 1 { input!(k: Usize1, c: char, d: char); trie.substitute(k, (c as u8 - b'a') as usize, (d as u8 - b'a') as usize); } else { input!(t: Chars); let ans = trie.search(&convert(&t)); println!("{ans}"); } } }