这个题用dfs递归做,会超时,要用动态规划解决。
关键点:如何定义能够被重复利用的dp[i]。
dp[j]
表示前
j
j
j 字符是否能分割成字典中的单词。
若要判断前
i
i
i(
i
>
j
i > j
i>j)个字符是否能够分割,仅需要判断
j
j
j~
(
i
−
j
)
(i- j)
(i−j) 的字符是否在字典中。
得到状态转移方程:
dp[i] = dp[j] && (s.substr(j, i) is in wordDict)
为了找到所有可能,将 j
从
0
0
0 ~
i
−
1
i-1
i−1 枚举。
进一步优化:不再遍历 j
的位置,而遍历wordDict
中所有的key值进行判断。
附上代码:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
map<string, int> m;
for(auto s : wordDict) m[s] = 1;
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] && m.count(s.substr(j, i-j))) {dp[i] = true; break;}
}
}
return dp.back();
}
};
优化后
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
map<string, int> m;
for(auto s : wordDict) m[s] = 1;
vector<bool> dp(s.size()+1);
dp[0] = true;
for(int i=1; i<=s.size(); i++){
for(auto x : m){
int l = x.first.size();
if(i >= l && dp[i-l] && x.first == s.substr(i-l, l)){
dp[i] = true; break;
}
}
}
return dp.back();
}
};