[LeetCode] 9 Word Split 2

Posted by hellangel on Mon, 25 May 2020 18:45:06 +0200

subject

140. Word Split II

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces to the string to construct a sentence so that all words in the sentence are in the dictionary.Return all these possible sentences.

Explain:

  • Words in the dictionary can be reused when separating.
  • You can assume that there are no duplicate words in the dictionary.
Example 1:

Input:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
Output:
[
  "cats and dog",
  "cat sand dog"
]
Example 2:

Input:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
Output:
[
  "pine apple pen apple",
  "pineapple pen apple",
  "pine applepen apple"
]
Explanation: Note that you can reuse words in the dictionary.
Example 3:
Input:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
Output:
[]

Method 1: Violence

algorithm

The easiest way to solve this problem is to use backtracking.To find out, we check that all possible prefixes of the string (ss) are in the dictionary, and if (for example, s1s1), call the backtrace function and check the remaining strings. If the rest can form a valid split, this function returns the prefix S1 S1 and follows the rest of the backtrace call (that is, s-S1 s_s1) after S1 s1.Otherwise, return to the empty list.

package com.janeroad;


import java.util.*;

public class test3 {
    public List<String> wordBreak(String s, Set<String> wordDict) {
        return word_Break(s, wordDict, 0);
    }
    public List<String> word_Break(String s, Set<String> wordDict, int start) {
        LinkedList<String> res = new LinkedList<>();
        if (start == s.length()) {
            res.add("");
        }
        for (int end = start + 1; end <= s.length(); end++) {
            if (wordDict.contains(s.substring(start, end))) {
                List<String> list = word_Break(s, wordDict, end);
                for (String l : list) {
                    res.add(s.substring(start, end) + (l.equals("") ? "" : " ") + l);
                }
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Set<String> testSet = new HashSet<String>();
        testSet.add("cat");
        testSet.add("cats");
        testSet.add("and");
        testSet.add("sand");
        testSet.add("dog");
        test3 test3=new test3();
        System.out.println(test3.wordBreak("catsanddog",testSet));
    }
}

Method 2: Memory backtracking

algorithm

In the previous method, we can see that many of the subproblems are redundant, that is, we call the function multiple times for the same substring.

To avoid this situation, we use a memory method, we use aKey:valuekeyHash tables such as value are optimized.In a hash table, keykey is the start subscript of the current considered string, and valuevalue contains all possible sentences from the beginning.The next time we encounter a call that starts at the same location, we can return the result directly from the hash table without having to recalculate the result.

With the method of memory, many redundant subproblems can be omitted and the backtrace tree is pruned, thus greatly reducing the time complexity.

public class Solution {

    public List<String> wordBreak(String s, Set<String> wordDict) {
        return word_Break(s, wordDict, 0);
    }
    HashMap<Integer, List<String>> map = new HashMap<>();

    public List<String> word_Break(String s, Set<String> wordDict, int start) {
        if (map.containsKey(start)) {
            return map.get(start);
        }
        LinkedList<String> res = new LinkedList<>();
        if (start == s.length()) {
            res.add("");
        }
        for (int end = start + 1; end <= s.length(); end++) {
            if (wordDict.contains(s.substring(start, end))) {
                List<String> list = word_Break(s, wordDict, end);
                for (String l : list) {
                    res.add(s.substring(start, end) + (l.equals("") ? "" : " ") + l);
                }
            }
        }
        map.put(start, res);
        return res;
    }
}

Method 3: Using dynamic planning

algorithm

public class Solution {
   public List<String> wordBreak(String s, Set<String> wordDict) {
       LinkedList<String>[] dp = new LinkedList[s.length() + 1];
       LinkedList<String> initial = new LinkedList<>();
       initial.add("");
       dp[0] = initial;
       for (int i = 1; i <= s.length(); i++) {
           LinkedList<String> list = new LinkedList<>();
           for (int j = 0; j < i; j++) {
               if (dp[j].size() > 0 && wordDict.contains(s.substring(j, i))) {
                   for (String l : dp[j]) {
                       list.add(l + (l.equals("") ? "" : " ") + s.substring(j, i));
                   }
               }
           }
           dp[i] = list;
       }
       return dp[s.length()];
   }
}

Topics: Programming REST Java