leet-code/longest-string-chain/sol.rs

55 lines
1.9 KiB
Rust

impl Solution {
pub fn get_max_chain_len(from: &Vec<Vec<usize>>, memos: &mut Vec<i32>, 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<String>) -> 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()
}
}