题目地址
https://leetcode-cn.com/problems/word-break/
题目描述:单词拆分
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:1. 拆分时可以重复使用字典中的单词。2. 你可以假设字典中没有重复的单词。
示例:
例 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
解答
动态规划可以很好的解决问题。
设置辅助数组 dp(s.size(), 0), 若 dp[i] == 1, 则证明 wordDict 中字符串可以表示 s[0, …, i]的字符;否则不能表示。
两重循环,第一层循环遍历 s, 第二层循环为 i - 1 ~ 0, 在第二层循环中,若 dp[j] == 1, 则字典中是否存在字符串 s[j+1, …,i], 若存在,则将 dp[i] 设置为 1 并退出第二层循环。如此反复,直到第一层循环结束。
代码:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
if( s.empty())
return true;
unordered_set<string> words;
for( auto it:wordDict)
words.insert( it);
vector<bool> dp(s.size(), 0);
for( int i = 0, j; i < s.size(); i++){
for( j = i - 1; j > -1; j--)
if( dp[j]){
dp[i] = words.find( s.substr( j + 1,i - j)) != words.end();
if( dp[i])
break;
}
if( j == -1)
dp[i] = words.find( s.substr( j + 1,i - j)) != words.end();
}
return dp.back();
}
};