https://leetcode.cn/problems/word-break/
题目要求
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
回溯
class Solution {
boolean same = false;
public boolean wordBreak(String s, List<String> wordDict) {
backtrack(s, wordDict, new StringBuilder());
return same;
}
public void backtrack(String s, List<String> wordDict, StringBuilder cur) {
if (cur.length() > s.length())
return;
if (cur.length() == s.length()) {
if (s.equals(cur.toString()))
same = true;
else
return;
}
for (int i = 0; i < wordDict.size() && !same; i++) {
cur.append(wordDict.get(i));
backtrack(s, wordDict, cur);
cur.delete(cur.length() - wordDict.get(i).length(), cur.length());
}
}
}
记忆化搜索
class Solution {
private int[] emeo;
private Set<String> wordSet = new HashSet<>();
public boolean wordBreak(String s, List<String> wordDict) {
for (String word : wordDict) wordSet.add(word);
emeo = new int[s.length()];
Arrays.fill(emeo, 0);
return backtrack(s, 0);
}
private boolean backtrack(String s, int start) {
if (start == s.length()) return true;
// 如果子问题已经处理过了,直接返回结果
if (emeo[start] != 0) return emeo[start] == 1;
for (int i = start; i < s.length(); i++) {
String subStr = s.substring(start, i + 1);
if (!wordSet.contains(subStr)) continue;
boolean subRes = backtrack(s, i + 1);
if (subRes) {
// 说明 [start...n-1] 是可以拆分成单词的
emeo[start] = 1;
return true;
}
}
// 已经完整遍历 [start...n-1] 都无法拆分
emeo[start] = -1;
return false;
}
}
动态规划
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
HashSet<String> set = new HashSet<>(wordDict);
boolean[] valid = new boolean[s.length() + 1];
valid[0] = true;
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i && !valid[i]; j++) {
if (set.contains(s.substring(j, i)) && valid[j]) {
valid[i] = true;
break;
}
}
}
return valid[s.length()];
}
}