leetcode 链接:139. 单词拆分
题目
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
- 拆分时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例:
输入: s = "leetcode", wordDict = ["leet", "code"]输出: true解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
注意你可以重复使用字典中的单词。
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false
解答 & 代码
先将字典中的单词存入哈希表 wordMap,提高查找效率
动态规划:
- 设置数组
dp,dp[i]代表字符串前i个字符(即s[0...i-1])能否被拆分成字典中的单词 - 初始化
dp[0] = true,即长度为 0 的空字符串可以被拆分 从
i = 1开始直到i = len,求dp[i]遍历每个切分点
j ∈ [0, i),状态转移方程为class Solution { public: bool wordBreak(string s, vector<string>& wordDict) { // 将字典中的单词存入哈希表,提高查找效率 unordered_set<string> wordMap; for(int i = 0; i < wordDict.size(); ++i) wordMap.insert(wordDict[i]); // 动态规划 int len = s.size(); vector<bool> dp(len + 1, false); // dp[i] 代表字符串前 i 个字符(即 s[0...i-1])能否被拆分成字典中的单词 dp[0] = true; for(int i = 1; i <= len; ++i) { for(int j = 0; j < i; ++j) { if(dp[j] && wordMap.find(s.substr(j, i - j)) != wordMap.end()) { dp[i] = true; break; } } } return dp[len]; } };执行结果: ``` 执行结果:通过
执行用时:20 ms, 在所有 C++ 提交中击败了 52.28% 的用户 内存消耗:12.7 MB, 在所有 C++ 提交中击败了 52.28% 的用户
对上述方法进行**剪枝**:<br />因为在枚举切分点 `j` 时,要在哈希表中查询 `s[j...i-1]` 是否存在,如果 `i - j` 的长度大于哈希表中最大单词长度 `maxWordLen`,那么肯定不存在,这些情况可以忽略。也就是说,遍历切分点 `j` 时,让 `j` 从 `max(0, i - maxWordLen)` 开始遍历
```cpp
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
// 将字典中的单词存入哈希表,提高查找效率
unordered_set<string> wordMap;
int maxWordLen = 0; // 单词表中最大单词长度
for(int i = 0; i < wordDict.size(); ++i)
{
wordMap.insert(wordDict[i]);
maxWordLen = wordDict[i].size() > maxWordLen ? wordDict[i].size() : maxWordLen;
}
// 动态规划
int len = s.size();
vector<bool> dp(len + 1, false); // dp[i] 代表字符串前 i 个字符(即 s[0...i-1])能否被拆分成字典中的单词
dp[0] = true;
for(int i = 1; i <= len; ++i)
{
// 剪枝:遍历切分点 j 时,让 j 从 max(0, i - maxWordLen) 开始遍历
int j = (i - maxWordLen >= 0) ? i - maxWordLen : 0;
for(; j < i; ++j)
{
if(dp[j] && wordMap.find(s.substr(j, i - j)) != wordMap.end())
{
dp[i] = true;
break;
}
}
}
return dp[len];
}
};
执行结果:
执行结果:通过
执行用时:4 ms, 在所有 C++ 提交中击败了 93.33% 的用户
内存消耗:7.5 MB, 在所有 C++ 提交中击败了 75.50% 的用户
