解法一 $O(n^2)$
这里采用了字符串hash的方法
class Solution {
public boolean wordBreak(String s, List wordDict) {
Set hash = new HashSet<>();
int n = s.length(), P = 131;
long Q = Long.MAX_VALUE;
for(String word : wordDict) {
// 采用字符串hash 的方式,减少
long h = 0;
for(char c : word.toCharArray()) h = h * P + c; // 这里可以 % Q,防止溢出
hash.add(h);
}
boolean[] f = new boolean[n + 1];
f[0] = true;
s = " " + s;
for(int i = 0; i < n; i ++) {
// 如果当前为true,代表前1~i个字符已经划分成功,可以从这个字符的下一个开始,向下扩展
if(f[i]) {
long h = 0;
for(int j = i + 1; j <= n; j ++) {
h = h * P + s.charAt(j);
if(hash.contains(h)) f[j] = true;
}
}
}
return f[n];
}
}
解法二 $O(n^3)$,
因为substring方法是$O(n)$,当然也可以把第二层for循环改成解法三那样,也可以不用字符串hash。
class Solution {
public boolean wordBreak(String s, List wordDict) {
Set set = new HashSet<>(wordDict);
int n = s.length();
boolean[] f = new boolean[n + 1];
s = " " + s;
// f[0]是合法的
f[0] = true;
// f[i]:表示1~i的合法划分是否存在
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= i; j ++) {
String t = s.substring(j, i + 1);
/*if(set.contains(t)) {
// System.out.println(t + " " + j + " " + i);
f[i] = f[j - 1];
// 只要f[i]为true,就代表1~i已经是合法划分成功。
// 那就直接跳出,防止被f[i]为false覆盖
if(f[i]) break;
}*/
if(set.contains(t) && f[j - 1]) f[i] = true;
}
}
return f[n];
}
}
解法三
class Solution {
public boolean wordBreak(String s, List wordDict) {
Set set = new HashSet<>(wordDict);
int n = s.length();
boolean[] f = new boolean[n + 1];
s = " " + s;
// f[0]是合法的
f[0] = true;
// f[i]:表示1~i的合法划分是否存在
for(int i = 0; i < n; i ++) {
if(f[i]) {
String t = "";
for(int j = i + 1; j <= n; j ++) {
t += s.charAt(j);
if(set.contains(t)) f[j] = true;
}
}
}
return f[n];
}
}