题目大意:给出字符串s和字典,用空格拆分字符串s,使得成为一个或多个在字典中出现的单词,找出所有可拆分的解。
分析:动态规划。先用leetcode139判断是否有解。有解的基础上:
状态:二维数组dp[i]——s[0~i-1]的所有可拆分情况(一堆字符串)
初始化:vector<string>均为空
结果:dp[s.size()]
转移方程:
如果s[0~i-i]有解——if(!dp[i].empty()) ,就遍历字典,依次拿出word匹配,如果有匹配当前s[i]的word:
对dp[i]中的每个字符串dp[i][j],dp[i+word.size()].push_back(dp[i][j] + “ ” + word)
代码:
class Solution {
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
if (!isBreakable(s, wordDict)) return {}; //先判断是否有解,否则超时
vector<vector<string>> dp(s.size() + 1, vector<string>());
for (int i = 0; i < s.size(); i++) { //找从s[i]开始的匹配解
//只有当s[0~i-1]有解时才从i开始继续找解
if (i == 0 || !dp[i].empty()) {
for (string word : wordDict) {
int newEnd = i + word.size();
if (newEnd > s.size()) continue;
if (s.substr(i, word.size()) != word) continue;
if (i == 0) { //注意从0开始的匹配解直接加入答案,不用加" "
dp[newEnd].push_back(word);
continue;
}
for (string str : dp[i]) {
dp[newEnd].push_back(str + " " + word);
}
}
}
}
return dp[s.size()];
}
bool isBreakable(string s, vector<string>& wordDict) {
unordered_set<string> words(wordDict.begin(),wordDict.end());
vector<bool> dp(s.size() + 1);
dp[0] = true;
for(int i = 1;i <= s.size();i++){
for(int j = 0;j < i;j++){
if(dp[j] && words.count(s.substr(j,i - j))){
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};