动态规划
- dp[i] 表示字符串 s[0…i−1] 是否能被空格拆分成若干个字典中出现的单词
- dp[i] = dp[j] && check(s[j … i-1])
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> myset(wordDict.begin(), wordDict.end());
int len = s.size();
vector<bool> dp(len+1,false);
dp[0] = true;
for(int i=1; i<=len; i++)
{
for(int j = 0; j<i; j++)
{
if(dp[j] && myset.find(s.substr(j, i-j))!=myset.end())
{
dp[i] = true;
break;
}
}
}
return dp[len];
}
};
递归:避免重复计算
- 缺点:依然存在诸多无效遍历
- 比如:dict中最短长度为10,10之前的子串遍历都是无效的
class Solution {
private:
unordered_set<string> mydict;
unordered_map<int, int> start_flag;
int str_len;
public:
bool dfs(string& s, int start)
{
if(start >= str_len)
return true;
if(start_flag.count(start))
return start_flag[start];
for(int i=start + 1; i<=str_len; i++)
{
string str = s.substr(start, i-start);
if(mydict.find(str) != mydict.end())
{
start_flag[start] = dfs(s, i);
if(start_flag[start])
return true;
}
}
return false;
}
bool wordBreak(string s, vector<string>& wordDict) {
mydict = unordered_set<string>(wordDict.begin(), wordDict.end());
str_len = s.size();
return dfs(s, 0);
}
};
- 逐个遍历字典中每个单词的长度len
- 然后截取start开始的len长度的字符串进行比较
class Solution {
private:
unordered_set<string> mydict;
unordered_map<int, int> start_flag;
int str_len;
int dict_len;
public:
bool dfs(string& s, int start, vector<string>& wordDict)
{
if(start >= str_len)
return true;
if(start_flag.count(start))
return start_flag[start];
for(auto& word : wordDict)
{
int wordsize = word.size();
string sub = s.substr(start, wordsize);
if(sub != word)
continue;
start_flag[start] = dfs(s, start + wordsize, wordDict);
if(start_flag[start])
return true;
}
return false;
}
bool wordBreak(string s, vector<string>& wordDict) {
mydict = unordered_set<string>(wordDict.begin(), wordDict.end());
str_len = s.size();
dict_len = wordDict.size();
return dfs(s, 0, wordDict);
}
};