Title:
Given a non empty string s and a dictionary wordDict containing a list of non empty words, add spaces in the string to build a sentence so that all the words in the sentence are in the dictionary. Return all these possible sentences.
Explain:
- You can reuse words in the dictionary when you separate them.
- 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" ] Note that you can reuse the words in the dictionary. Example 3: Input: s = "catsandog" wordDict = ["cats", "dog", "sand", "and", "cat"] Output: []
Train of thought:
Use dynamic programming to determine whether there is a solution. Then depth first search all solutions.
Code:
public static List<String> wordBreak(String s, List<String> wordDict) { List<String> res = new ArrayList<String>(); //Whether dynamic planning can be executed boolean[] dp = new boolean[s.length()+1]; dp[0] = true; for(int i=0 ;i<=s.length();i++){ for(int j=0;j<i;j++){ String k = s.substring(j,i); if(dp[j] && wordDict.contains(k)){ dp[i]=true; break; } } } int l = s.length(); if(!dp[l]){ return res; } StringBuilder ssr = new StringBuilder(); dfs(s,wordDict,ssr,res,0); return res; } //Depth first search to find the solution. private static void dfs(String s,List<String> wordDict,StringBuilder ssr,List<String> res,int start){ if(start == s.length()){ res.add(ssr.toString().trim()); return; } for(int i=start+1;i<=s.length();i++){ String str = s.substring(start,i); if(wordDict.contains(str)){ int length = ssr.length(); ssr.append(str).append(" "); dfs(s,wordDict,ssr,res,i); ssr.setLength(length); } } }
/ / improved method:
class Solution { public List<String> wordBreak(String s, List<String> wordDict) { List<String> res = new ArrayList<>(); int max = 0, min = Integer.MAX_VALUE; Set<String> set = new HashSet<>(); for (String word : wordDict) { set.add(word); max = Integer.max(max, word.length()); min = Integer.min(min, word.length()); } boolean f[] = new boolean[s.length() + 1]; f[0] = true; for (int i = 1; i < s.length() + 1; i++) { for (int j = Math.max(i - max, 0); j <= i - min; j++) { if (f[j] && set.contains(s.substring(j, i))) { f[i] = true; break; } } } if (f[s.length()]) { dfs(s, res, new StringBuilder(), set, 0, max, min); } return res; } private void dfs(String s, List<String> res, StringBuilder sb, Set<String> set, int index, int max, int min) { if (index == s.length()) { sb.deleteCharAt(sb.length() - 1); res.add(sb.toString()); return; } String str; int size; for (int i = index + min; i <= s.length() && i <= index + max; i++) { if (set.contains(str = s.substring(index, i))) { size = sb.length(); sb.append(str).append(' '); dfs(s, res, sb, set, i, max, min); sb.delete(size, sb.length()); } } } }