Word Ladderと同じ入力に対し、最短距離の複数パスを配列として返す問題。BFSで各ノードへの最短距離を探し、DFSでEnd Nodeへの最短パスを作成することで解くことができる。
use std::collections::{HashMap, HashSet, VecDeque}; #[derive(Default)] struct Graph { neighbors: HashMap<String, HashSet<String>>, distance: HashMap<String, usize>, end: String, stack: Vec<String>, output: Vec<Vec<String>>, } impl Graph { fn dfs(&mut self, word: &str) { self.stack.push(word.to_string()); if word == self.end { self.output.push(self.stack.clone()); self.stack.pop(); return; } let neighbors = self.neighbors.get(word).cloned(); if let Some(neighbors) = neighbors { for neighbor in neighbors.iter() { if self.distance[neighbor] == self.distance[word] + 1 { self.dfs(neighbor); } } } self.stack.pop(); } } pub fn find_ladders( begin_word: String, end_word: String, word_list: Vec<String>, ) -> Vec<Vec<String>> { let mut word_dict: HashMap<String, Vec<String>> = HashMap::new(); for word in word_list.into_iter() { for i in 0..word.len() { let new_word = [&word[..i], "*", &word[i + 1..]].join(""); word_dict.entry(new_word).or_default().push(word.clone()); } } let mut queue = VecDeque::new(); queue.push_back((begin_word.clone(), 0)); let mut visited = HashSet::new(); visited.insert(begin_word.clone()); let mut graph: Graph = Default::default(); graph.end = end_word; // Run BFS to find minimum distance to each node while let Some((word, depth)) = queue.pop_front() { graph.distance.insert(word.clone(), depth); for i in 0..word.len() { let new_word = [&word[..i], "*", &word[i + 1..]].join(""); if let Some(matched_words) = word_dict.get(&new_word) { for matched in matched_words.iter() { graph .neighbors .entry(word.clone()) .or_default() .insert(matched.clone()); graph .neighbors .entry(matched.clone()) .or_default() .insert(word.clone()); if !visited.contains(matched) { queue.push_back((matched.clone(), depth + 1)); visited.insert(matched.clone()); } } } } } // Run DFS to find multiple path to end node graph.dfs(&begin_word); graph.output }
計算量はWord Ladderと同じくO(M2 * N)