Description:
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words.
For example, given
s = "leetcode"
,
dict = ["leet", "code"]
.
Return true because "leetcode"
can be segmented as "leet code"
.
UPDATE (2017/1/4):
The wordDict parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.
简要题解:
采用动态规划。
子问题i:字符串中从第0个元素(为空)到第i个元素的子串。
每个子问题维护一个值: 是否可以将该子串分割为一个或多个字典单词的空格分隔序列(初始时,全假定为false)。对于第一个子问题,其对应的值c(0)=true。
c(i)与c(i-1)的关系: 在进行c(i)时,首先先确认c(i-1)是否为true。如果不是,则跳过该子问题。否则,一一确认字典dict中以目标字符串s的第i个元素为开头的单词是否与以第i个元素为开头的原字符串中的某个子串相等,如果是的话,假定该子串的长度为len,则有c(i - 1 + len) = true。如果不是,不做任何处理。(初始化时每个子问题都假定为false,在迭代过程中,如果某一个子问题都没有被赋予过true的话,那false就自动是它最终的值)
从i = 1开始,一直迭代下去,直至子问题成为该问题本身。则,该子问题维护的那个真假值就是所要求的。(某些情况下也可以提前终止,如在处理第i个子问题时,c(i - 1 + len) = true刚好为原问题本身,则可直接返回true。不过在这里,我没有实现。因为性能并没有得到明显的提升)
代码:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
vector<bool> dp(s.size() + 1, false);
int sz;
dp[0] = true;
for (int i = 1; i <= s.size(); i++) {
if (!dp[i-1])
continue;
for (int j = 0; j < wordDict.size(); j++) {
sz = wordDict[j].size();
if (i - 1 + sz > s.size())
continue;
if (s.substr(i - 1, sz) == wordDict[j]) {
dp[i-1+sz] = true;
cout << wordDict[j] << endl;
}
}
}
return dp[s.size()];
}
};