题目
方法一:DFS
我采用的DFS极其愚蠢,把全排列的思想套到了这题上,用DFS穷举出wordDict中所有的排列那去和s做比较,效率及其低,不出意料的超时;
class Solution {
public:
bool flag = false;
bool wordBreak(string s, vector<string>& wordDict) {
string tmp;
DFS(s,wordDict,tmp);
return flag;
}
void DFS(string &s, vector<string>& wordDict, string &tmp)
{
if(flag == true)
return;
if(tmp.size()>=s.size())
{
//cout<<tmp<<endl;
if(tmp.size()==s.size()&&!tmp.compare(s))
flag = true;
return;
}
for(int i=0;i<tmp.size();i++)
{
if(tmp[i]!=s[i])
return;
}
for(int i=0;i<wordDict.size();i++)
{
tmp.append(wordDict[i]);
DFS(s,wordDict,tmp);
if(tmp.size()!=0)
tmp = tmp.substr(0,tmp.size() - wordDict[i].size());
}
}
};
方法二:动态规划
其状态转移为:dp[i]表示字符串s的前i个字符能否拆分成wordDict中的元素,那么dp[j]是否为true就取决于dp[i]是否为true并且i到j之间的字符串包含在wordDict中; 程序表述:
if(dp[j] && find(wordDict.begin(),wordDict.end(),s.substr(j,i-j))!=wordDict.end())
dp[i] = true;
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
vector<bool> dp(s.size()+1,false);
dp[0] = true;
for(int i=1;i<=s.size();i++)
{
for(int j=0;j<i;j++)
{
if(dp[j] && find(wordDict.begin(),wordDict.end(),s.substr(j,i-j))!=wordDict.end())
dp[i] = true;
}
}
return dp[s.size()];
}
};
还可以优化,j不一定要每次都从0起步,其检查范围应当在wordDict中的最长元素的长度范围内;
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
vector<bool> dp(s.size()+1, false);
unordered_set<string> m(wordDict.begin(), wordDict.end());
dp[0] = true;
//获取最长字符串长度
int maxWordLength = 0;
for (int i = 0; i < wordDict.size(); ++i){
maxWordLength = std::max(maxWordLength, (int)wordDict[i].size());
}
for (int i = 1; i <= s.size(); ++i){
for (int j = std::max(i-maxWordLength, 0); j < i; ++j){
if (dp[j] && m.find(s.substr(j, i-j)) != m.end()){
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};