题目描述:
给定一个非空字符串 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 动态规划
主要思路:
(1)对字符串从头开始,使用每一个字典中的元素,在字符串中做匹配,若是成功,则进行记录;
(2)对整个字符串的每个元素进行判断,返回最后的一个元素;
(3)匹配的过程中,首先要满足当前的位置之前的字符串是可以使用字典内的字符串进行表示的,既dp[i]为true,其次,保证当前位置加上当前字典内的字符串后不会越界,既i+word.size()<dp.size(),最后子字符串和字典内的字符串匹配成功,既s.substr(i,word.size())==word,如此则记录匹配后的位置,既 dp[i+word.size()]=true;
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
//初始化标识的动态数组
vector<bool> dp(s.size()+1,false);
//首位置为true,表示可以从此位置开始遍历
dp[0]=true;
//遍历字符串的每个位置
for(int i=0;i<dp.size();++i){
//遍历字典内的每个字符串
for(auto word:wordDict){
//判断当前字典内的字符串能否和字符串内的子字符串匹配上
//先要满足当前的位置之前的字符串是可以使用字典内的字符串进行表示的,既dp[i]为true
//其次,保证当前位置加上当前字典内的字符串后不会越界,既i+word.size()<dp.size()
//最后子字符串和字典内的字符串匹配成功,既s.substr(i,word.size())==word
if(dp[i]&&i+word.size()<dp.size()&&s.substr(i,word.size())==word){
//如此则记录匹配后的位置,既 dp[i+word.size()]=true;
dp[i+word.size()]=true;
}
}
}
return dp.back();
}
};
可能的优化方向:
(1)将字典内的字符串根据长度,进行分组,则对于同一样的长度的字符数组,在判断出前面的某个匹配上之后,后面的同样长度的字符串就可以不再进行匹配;
(2)使用深度搜索的思路,在匹配时,尽量向后进行匹配,希望能够提前的到达终点的位置,若是此位置满足要求了,就不用再判断其他的可能的结果。