impl Solution { pub fn get_max_chain_len(from: &Vec>, memos: &mut Vec, start: usize) -> i32 { let memo_val = *memos.get(start).unwrap_or(&-1); if memo_val != -1 { return memo_val; } let max_len = from.get(start) .unwrap() .iter() .map(|&next| Solution::get_max_chain_len(from, memos, next)) .max() .unwrap_or(0) + 1; memos[start] = max_len; max_len } #[inline] pub fn is_predecessor(word: &String, of_word: &String) -> bool { let mut skipped = false; let mut oi = of_word.bytes(); of_word.len() == word.len() + 1 && word.bytes() .all(|chr| { if chr == oi.next().unwrap() { // Before extra character true } else if !skipped && chr == oi.next().unwrap() { // Extra character, skipped ensures this can only run once skipped = true; true } else { false } }) } pub fn longest_str_chain(words: Vec) -> i32 { let (mut from, mut to) = (vec![vec![]; words.len()], vec![true; words.len()]); for (idx1, w1) in words.iter().enumerate() { for (idx2, w2) in words.iter().enumerate() { if Solution::is_predecessor(w1, w2) { from[idx1].push(idx2); to[idx2] = false; } } } let mut memos = vec![-1; words.len()]; to.into_iter() .enumerate() .filter_map(|(to, froms)| { if froms { Some(Solution::get_max_chain_len(&from, &mut memos, to)) } else { None } }) .max() .unwrap() } }