Copy Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.
Note:
The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.
Example 1:
Input:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
Output:
[
"cats and dog",
"cat sand dog"
]
Approach 1: Recursion with memoization
Copy class Solution {
public List < String > wordBreak ( String s , List < String > wordDict) {
HashMap < Integer , List < String >> memo = new HashMap() ;
return dfs(s , 0 , wordDict , memo) ;
}
private List < String > dfs ( String s , Integer start , List < String > wordDict , HashMap < Integer , List < String >> memo) {
if ( memo . get (start) != null ) {
return memo . get (start);
}
List < String > ans = new LinkedList() ;
if (start == s . length ()) {
ans . add ( "" );
return ans;
}
for ( String word : wordDict) {
for ( int end = start + 1 ; end <= s . length (); end ++ ) {
String w = s . substring (start , end);
if ( word . equals (w)) {
List < String > list = dfs(s , end , wordDict , memo) ;
for ( String str : list) {
String seq = word + ( str . length () > 0 ? " " : "" ) + str;
ans . add (seq);
}
}
}
}
memo . put (start , ans);
return ans;
}
}
Approach #3 Using Dynamic Programming (Time Limit Exceeded)
Copy 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]) {
String w = l + ( l . equals ( "" ) ? "" : " " );
list . add (w + s . substring (j , i));
}
}
}
dp[i] = list;
}
return dp[ s . length ()];
}
}
Copy class Solution {
public List < String > wordBreak ( String s , List < String > wordDict) {
Set < String > wordSet = new HashSet <>(wordDict);
// Check if there is at least one possible sentence
boolean [] dp1 = new boolean [ s . length () + 1 ];
dp1[ 0 ] = true ;
for ( int i = 1 ; i <= s . length (); i ++ ) {
for ( int j = 0 ; j < i; j ++ ) {
if (dp1[j] && wordSet . contains ( s . substring (j , i))) {
dp1[i] = true ;
break ;
}
}
}
// We are done if there isn't a valid sentence at all
if ( ! dp1[ s . length ()]) {
return new ArrayList < String >();
}
// Build the results with dynamic programming
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 && wordSet . 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 ()];
}
}
Copy class Solution {
public List < String > wordBreak ( String s , List < String > wordDict) {
return backtrace(s , wordDict , new HashMap < String , LinkedList < String >>()) ;
}
List < String > backtrace ( String s , List < String > wordDict , HashMap < String , LinkedList < String >> map) {
if ( map . containsKey (s)) return map . get (s);
LinkedList < String > res = new LinkedList < String >();
if ( s . length () == 0 ) {
res . add ( "" );
return res;
}
for ( String word : wordDict) {
if ( s . startsWith (word)) {
List < String > sublist = backtrace( s . substring( word . length()) , wordDict , map) ;
for ( String sub : sublist) {
res . add (word + ( sub . isEmpty () ? "" : " " ) + sub);
}
}
}
map . put (s , res);
return res;
}
}