单词拆分
很好的一道完全背包的问题。彻底把我迷晕了,哈哈哈哈。但是看了解析之后还是清晰了不少。
将dict
中的单词看做物品,s.size()
看做背包总容量,dp[i]
表示长度为 i 的s子串能否由dict
中的单词组成。然后注意下面几个要点:
- 完全背包——从前往后遍历;
- 单词组成要求有序——先遍历背包再遍历物品
- 递推公式——
dp[i]=dp[i-len]||dp[i];
表示当前位置能否由dict
中物品组成,取决于之前的状态和前面一个单词的状态,这里用||
,就有那种dp[j]=max(dp[j],dp[j-w[i]]
的味道了 - 初始化——
dp[0]=true
,空串,也不是不行。但是这里必须设置为真,因为我们的递推公式
AC:
//显然,一个物品可以用多次,但是本题不同于数字,所以需要一个判断,判断的内容就是截取的内容,看能否在dict中找到
bool wordBreak(string s, vector<string>& wordDict)
{
vector<bool>dp(s.size()+1,false); //dp[i] 表示长度为i的s串的子串,能否由dict组成
dp[0]=true;
for(int i=0;i<=s.size();i++) //因为s是dict的顺序排列,相当于求排列数,先背包再物品
for(int j=0;j<wordDict.size();j++) //遍历物品 //完全背包 从前往后遍历
{
int len=wordDict[j].size();
if(i>=len)
{
string word=s.substr(i-len,len); //向前截取
if(word==wordDict[j]) dp[i]=dp[i-len]||dp[i]; //如果最近的单词匹配上,那就和之前的状态一致
}
}
return dp[s.size()];
}