題目大意:給出字符串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()];
}
};