|
// Approach #1 DFS + MEMO O(n * 3) T O(n * n) S |
|
// Approach #2 DP O(n * 3) T O(n * n) S |
|
// With maxLength optimization it can be O(n * maxLength * maxLength). |
|
|
|
// Approach #1 DFS + MEMO O(n * 3) T O(n * n) S |
|
public class Solution { |
|
/** |
|
* @param s: A string |
|
* @param dict: A set of word |
|
* @return: the number of possible sentences. |
|
*/ |
|
public int wordBreak3(String s, Set<String> dict) { |
|
// handle corner cases |
|
if (dict == null || dict.size() == 0 || s == null || s.length() == 0) { |
|
return 0; |
|
} |
|
|
|
// make it case insensitive |
|
Set<String> words = new HashSet<>(); |
|
for (String word : dict) { |
|
words.add(word.toLowerCase()); |
|
maxLength = Math.max(maxLength, word.length()); |
|
} |
|
|
|
// prep for MEMO |
|
dp = new int[s.length()][s.length()]; |
|
for (int[] row : dp) { |
|
Arrays.fill(row, -1); |
|
} |
|
|
|
// perform the MEMO search |
|
return dfs(words, s.toLowerCase(), 0, s.length() - 1); |
|
} |
|
|
|
private int maxLength; |
|
private int[][] dp; |
|
|
|
private int dfs(final Set<String> words, final String originalString, final int left, final int right) { |
|
if (left > right) { |
|
return 1; |
|
} |
|
if (dp[left][right] != -1) { |
|
return dp[left][right]; |
|
} |
|
|
|
int counter = 0; |
|
for (int i = left; i <= right && (i - left < maxLength); i++) { |
|
String word = originalString.substring(left, i + 1); |
|
|
|
if (!words.contains(word)) { |
|
continue; |
|
} |
|
counter += dfs(words, originalString, i + 1, right); |
|
} |
|
dp[left][right] = counter; |
|
|
|
return dp[left][right]; |
|
} |
|
} |
|
|
|
// Approach #2 DP O(n * 3) T O(n * n) S |
|
public class Solution { |
|
/** |
|
* @param s: A string |
|
* @param dict: A set of word |
|
* @return: the number of possible sentences. |
|
*/ |
|
public int wordBreak3(String s, Set<String> dict) { |
|
// handle corner cases |
|
if (dict == null || dict.size() == 0 || s == null || s.length() == 0) { |
|
return 0; |
|
} |
|
|
|
// make words case insensitive |
|
Set<String> words = new HashSet<>(); |
|
int maxLength = 0; |
|
for (String word : dict) { |
|
words.add(word.toLowerCase()); |
|
maxLength = Math.max(maxLength, word.length()); |
|
} |
|
|
|
// dp initialize |
|
String string2Break = s.toLowerCase(); |
|
int stringLength = string2Break.length(); |
|
int[][] dp = new int[stringLength][stringLength]; |
|
for (int i = 0; i < stringLength; i++) { |
|
for (int j = i; j < stringLength && (j - i < maxLength); j++) { |
|
String sub = string2Break.substring(i, j + 1); |
|
if (words.contains(sub)) { |
|
dp[i][j] = 1; |
|
} |
|
} |
|
} |
|
|
|
// dp fill the rest with dual-for loop |
|
for (int i = 0; i < stringLength; i++) { |
|
for (int j = i; j < stringLength; j++) { |
|
for (int k = i; k < j; k++) { |
|
dp[i][j] += dp[i][k] * dp[k + 1][j]; |
|
} |
|
} |
|
} |
|
|
|
return dp[0][stringLength - 1]; |
|
} |
|
} |