Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given s = “leetcode”, dict = ["leet", "code"].Return true because “leetcode” can be segmented as “leet code”.
1. Naive Approach
This problem can be solve by using a naive approach, which is trivial. A discussion can always start from that though.
public class Solution { public boolean wordBreak(String s, Set<String> dict) { return wordBreakHelper(s, dict, 0); } public boolean wordBreakHelper(String s, Set<String> dict, int start){ if(start == s.length()) return true; for(String a: dict){ int len = a.length(); int end = start+len; //end index should be <= string length if(end > s.length()) continue; if(s.substring(start, start+len).equals(a)) if(wordBreakHelper(s, dict, start+len)) return true; } return false; } } |
Time: O(2^n)
2. Dynamic Programming
The key to solve this problem by using dynamic programming approach:
public class Solution { public boolean wordBreak(String s, Set<String> dict) { boolean[] t = new boolean[s.length()+1]; t[0] = true; //set first to be true, why? //Because we need initial state for(int i=0; i<s.length(); i++){ //should continue from match position if(!t[i]) continue; for(String a: dict){ int len = a.length(); int end = i + len; if(end > s.length()) continue; if(t[end]) continue; if(s.substring(i, end).equals(a)){ t[end] = true; } } } return t[s.length()]; } } |
Time: O(string length * dict size)
One tricky part of this solution is the case:
INPUT: "programcreek", ["programcree","program","creek"].
We should get all possible matches, not stop at “programcree”.
3. The More Interesting Problem
The dynamic solution can tell us whether the string can be broken to words, but can not tell us what words the string is broken to. So how to get those words?
Possible Solution 1 (from jk451):
Change the “t” array to integer instead of boolean.
Replacing setting t[end] to true (i.e. saying you have found a break up of 0..end substring] with setting t[end] to i, thus saying you have found a break up of 0..end substring and the last word in that break up is substring i..end of the main string.
Then at the end if I can break up the string, I check t[s.length()]. THe last word in the break up will substring starting at t[s.length()] and ending at s.length()-1. And you repeate this procedure to get the other words.