方法一:
思路:利用记忆数组memo[i]定义为范围为[0, i)的子字符串是否可以拆分,初始化为-1,表示没有计算过,如果可以拆分,则赋值为1,反之为0。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict)
{
vector<int> memo(s.size(), -1);
unordered_set<string> wordset(wordDict.begin(), wordDict.end());
return helper(s, wordset, 0, memo);
}
bool helper(string s, unordered_set<string> &wordset, int start, vector<int>& memo)
{
if (start == s.size()) return true;
if (memo[start] != -1) return memo[start];
for (int i = start+1; i <= s.size(); ++i)
{
if (wordset.count(s.substr(start, i - start)) && helper(s, wordset, i, memo))
return memo[start] = 1;
}
return memo[start] = 0;
}
};
方法二:
思路:一般字符串匹配,拆分的问题,都会想到动态规划。当然关键还是找到递推公式。
我们只需要遍历一次字符串,当遍历到第i个字符时(下标为i-1),只需要[0,i)的范围内,有一个j满足dp[j]= =true,并且从j到i的字符串[j,i)即s.substr(j, i - j)在字典里,我们就可以将dp[j]设为true。如果在[0,i)的范围内,没有一个j满足条件,则在第i个字符处的后面不能拆分,继续遍历下一个点。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict)
{
unordered_set<string> wordset(wordDict.begin(), wordDict.end());
vector<bool> dp(s.size() + 1);
dp[0] = true;
for (int i = 1; i <= s.size(); ++i)
{
for (int j = 0; j < i; ++j)
if (dp[j] && wordset.count(s.substr(j, i - j)))
{
dp[i] = true;
break;
}
}
return dp[s.size()];
}
};