leetcode:139. 单词拆分 - 力扣(LeetCode)
题目
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
- 输入: s = "leetcode", wordDict = ["leet", "code"]
- 输出: true
- 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
示例 2:
- 输入: s = "applepenapple", wordDict = ["apple", "pen"]
- 输出: true
- 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
- 注意你可以重复使用字典中的单词。
示例 3:
- 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
- 输出: false
思路
(1)dp[i]: 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
(2)如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。
递推公式为:
if([j,i] && dp[j]==true){
dp[i]=true;}
(3)这里怎么看排列顺序呢?
(4)dp[0]一定为true,不然后面根据递推公式会一直为false。
#include <vector>
#include <unordered_set>
using namespace std;
class Solution
{
public:
/**
* 使用动态规划方法解决单词拆分问题
*
* @param s 待拆分的字符串
* @param wordDict 单词字典,包含可以用于拆分的单词
* @return bool 表示字符串s是否可以由字典中的单词拆分
*
* 该函数通过动态规划的方式判断字符串s是否可以由字典中的单词连续拆分。
* 动态规划数组dp用于记录字符串的每一个位置是否可以被字典中的单词拆分。
* unordered_set用于存储单词字典,以提高查找效率。
*/
bool wordBreak(string s, vector<string> &wordDict)
{
// 将单词字典转换为unordered_set,提高查找效率
unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
// 初始化动态规划数组,大小为字符串长度+1,初始值均为false
vector<bool> dp(s.size() + 1, false);
// 设置初始条件,空字符串视为可以拆分
dp[0] = true;
// 遍历字符串s的所有子串,从1到s.size()逐步构建dp数组(j表示背包)
for (int j = 1; j <= s.size(); j++)
{
// 对于每个j,向前检查所有可能的子串(i表示物品)
for (int i = 0; i < j; i++)
{
// 提取子串s[i:j]
string word = s.substr(i, j - i);
// 如果该子串在字典中找到,且dp[i]为true,则说明s[0:j]可以拆分
if (wordSet.find(word) != wordSet.end() && dp[i] == true)
{
// 更新dp数组
dp[j] = true;
// 找到一种拆分方法即可,跳出循环
break;
}
}
}
// 返回最终的拆分结果
return dp[s.size()];
}
};
总结
从小到大逐渐找s的子串,看子串是不是数组里面的元素。