题目

思路
动态规划
这道题可以利用动态规划来判断字符串 s 是否能被拆分成字典 wordDict 中的单词。具体做法是:先将字典存入哈希集合以便快速查找,然后初始化一个 dp 数组,其中 dp[i] 表示 s 的前 i 个字符能否被拆分。初始时 dp[0] 设为 true(空字符串可拆分),接着遍历字符串,对于每个位置 i,检查所有可能的分割点 j,如果前 j 个字符可拆分(dp[j] 为 true)且子串 s[j..i-1] 在字典中,则标记 dp[i] 为 true。最终,dp[s.size()] 的值即为整个字符串 s 是否能被拆分的结果。
代码详解
首先我们可以将wordDict中的单词全都存入哈希表中,方便后面的判断。
接着定义dp,它是用来判断前面的字符能否被拆分。若dp[i]为false,则表示不可以。相反,若为true则为可以。
至于为什么创建它时空间为s.size()+1
因为 dp[i] 表示的是 前 i 个字符,而 s 的索引是从 0 开始的:
s[0..i-1] 对应 dp[i](前 i 个字符)。
如果 dp 的大小是 s.size(),那么 dp[s.size()] 就无法表示整个字符串(因为 s.size() 是 8,但 dp[8] 需要表示 s[0..7])。
dp[0]=true意味着空字符串可以被拆分
i变量是用来遍历所有可能的前缀长度,j是用来遍历所有的分割点。
s[0,j-1]能否被拆分(由dp[j])决定
s[j,i]是否在字典中(由 wordDictSet.find() 决定)
代码
cpp
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict)
{
auto wordDictSet = unordered_set<string> ();
for(auto &x: wordDict)
{
wordDictSet.insert(x);
}
vector<bool> dp(s.size()+1); // 默认是false
dp[0]=true;
for(int i=1;i<=s.size();i++)
{
for(int j=0;j<i;j++)
{
if(wordDictSet.find(s.substr(j,i-j))!=wordDictSet.end() && dp[j])
{
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};