题目
给定一个非空字符串 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
思路
- 使用动态规划。dp[i]表示s的前i个字符组成的字符串是否出现在wordDict中。为了查询速度,可以先把wordDict的词放到一个hash set里。
- dp[i]为true时,说明存在j使得 d p [ j ] = t r u e 并 且 s . s u b s t r ( j , i − j ) dp[j] = true 并且 s.substr( j, i-j) dp[j]=true并且s.substr(j,i−j)也在字典中。
代码
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
if ( !s.size() || !wordDict.size() )
return false;
vector<int> dp( s.size() + 1, false );
unordered_set mySet( wordDict.begin(), wordDict.end() );
int minSize = INT_MAX;
int maxSize = INT_MIN;
for ( auto& word : wordDict )
minSize = word.size() < minSize ? word.size() : minSize;
dp[0] = true;
for ( int i = minSize; i <= s.size(); ++i ) {
for ( int j = 0; j < i; ++j ) {
if ( dp[j] && mySet.count( s.substr(j, i-j ) ) ) {
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};