|
@@ -0,0 +1,109 @@
|
|
|
+struct Solution;
|
|
|
+
|
|
|
+use std::collections::HashSet;
|
|
|
+
|
|
|
+impl Solution {
|
|
|
+ pub fn word_break(s: String, word_dict: Vec<String>) -> Vec<String> {
|
|
|
+ let mut min_length = usize::MAX;
|
|
|
+ let mut max_length = 0;
|
|
|
+ let mut word_dict_2 = HashSet::new();
|
|
|
+ for w in word_dict {
|
|
|
+ let l = w.len();
|
|
|
+ if l < min_length { min_length = l; }
|
|
|
+ if l > max_length { max_length = l; }
|
|
|
+ word_dict_2.insert(w);
|
|
|
+ }
|
|
|
+
|
|
|
+ let dp = Solution::valid_wb(s.clone(), &word_dict_2, s.len(), min_length);
|
|
|
+ // println!("dp: {:?}", dp);
|
|
|
+
|
|
|
+ let mut res = vec![];
|
|
|
+ let mut cur = vec![];
|
|
|
+ if dp[0][s.len()-1] {
|
|
|
+ Solution::helper(s.clone(), &dp, s.len(), 0, &mut cur, &mut res, &word_dict_2);
|
|
|
+ }
|
|
|
+
|
|
|
+ res
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ fn helper(s: String, dp: &Vec<Vec<bool>>, n: usize, idx: usize, cur: &mut Vec<String>, res: &mut Vec<String>, word_dict: &HashSet<String>) {
|
|
|
+ if idx == n {
|
|
|
+ res.push(cur.join(" "));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for i in idx..n {
|
|
|
+ if !dp[idx][i] { continue; }
|
|
|
+ if word_dict.contains(&s[idx..i+1].to_string()) {
|
|
|
+ cur.push(s[idx..i+1].to_string());
|
|
|
+ Solution::helper(s.clone(), dp, n, i+1, cur, res, word_dict);
|
|
|
+ cur.pop();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ fn valid_wb(s: String, word_dict: &HashSet<String>, n: usize, min_length: usize) -> Vec<Vec<bool>> {
|
|
|
+
|
|
|
+ let mut dp = vec![vec![false; n]; n];
|
|
|
+
|
|
|
+ for i in 0..n {
|
|
|
+ if word_dict.contains(&s[i..i+1].to_string()) {
|
|
|
+ dp[i][i] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for l in 2..=n {
|
|
|
+ if l < min_length { continue; }
|
|
|
+ for i in 0..(n-l+1) {
|
|
|
+ let j = i + l - 1;
|
|
|
+
|
|
|
+ let end = j + 1;
|
|
|
+ if word_dict.contains(&s[i..end].to_string()) {
|
|
|
+ dp[i][j] = true;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for k in i..j {
|
|
|
+ dp[i][j] = dp[i][j] || (dp[i][k] && dp[k+1][j]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ dp
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+mod tests {
|
|
|
+ use super::*;
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_word_break() {
|
|
|
+ let s = String::from("catsanddog");
|
|
|
+ let word_dict = vec![String::from("cats"), String::from("dog"), String::from("sand"), String::from("and"), String::from("cat")];
|
|
|
+ let res = Solution::word_break(s, word_dict);
|
|
|
+ let expect = vec![String::from("cat sand dog"),String::from("cats and dog")];
|
|
|
+ assert_eq!(res, expect);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_word_break2() {
|
|
|
+ let s = String::from("a");
|
|
|
+ let word_dict = vec![String::from("a")];
|
|
|
+ let res = Solution::word_break(s, word_dict);
|
|
|
+ let expect = vec![String::from("a")];
|
|
|
+ assert_eq!(res, expect);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_word_break3() {
|
|
|
+ let s = String::from("ab");
|
|
|
+ let word_dict = vec![String::from("a"), String::from("b")];
|
|
|
+ let res = Solution::word_break(s, word_dict);
|
|
|
+ let expect: Vec<String> = vec![String::from("a b")];
|
|
|
+ assert_eq!(res, expect);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|