问题一(判断能否进行单词拆分):给出一个字符串,问能否将其拆分为1或多个单词。单词表已给出。
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode",
dict = ["leet", "code"].
Return true because "leetcode" can be segmented as "leet code".
思路:直观思路是递归尝试进行。但是超时。注意,递归尝试往往会重复把一件已经做过的事情做很多次。
而另外一个算法,动态规划,则是借助空间暂存结果,待到下次需要用的时候直接拿结果。这是递归和DP的重要区别。
递归和DP的重要相同点是,都存在子问题。
这道题用动态规划算法的话,会变得非常的快。
状态量H[i],表示字符串s的前i个字符组成的子串是否能够进行单词拆分。
递推关系:k from 0 to i-1,只要有一个k满足 H[k]==1 且 s[k...i-1]是一个单词。则表明H[i]是比H[k]多加了一个单词,因此H[i]等于1.
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int n = s.size();
if(n ==0)
return false;
int H[n+1];//H[i]表示s中前i个字符是否能进行word break
memset(H,0,sizeof(H));
H[0] = 1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<i;j++)
if(H[j] == 1 && dict.find(s.substr(j,i-j)) != dict.end())
{
H[i] = 1;
break;
}
}
return (H[n]==1);
}
};
问题二(进行单词拆分):Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.Return all such possible sentences.
For example, given
s = "catsanddog"
,
dict = ["cat", "cats", "and", "sand", "dog"]
.
A solution is ["cats and dog", "cat sand dog"]
.
思路:首先利用上面的动态规划方法判断能否进行拆分。然后利用backtrack方法生成所有组合。
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
vector<string> re;
int n = s.size();
if(n == 0)
return re;
int H[n+1];
memset(H, 0, sizeof(H));
H[0] = 1;
for(int i=1; i<=n;i++)
{
for(int j=0;j<i;j++)
{
if(H[j] == 1 && dict.find(s.substr(j, i-j)) != dict.end() )
{
H[i] = 1;
break;
}
}
}
if(H[n] == 0) // 先利用DP方法检验是否能够拆分单词
return re;
string now = "";
backtrack(s, now, 0, H, n, dict, re); //再用backtrack方法进行组合生成
return re;
}
void backtrack(string &s, string &now, int idx, int H[], int n, unordered_set<string> &dict, vector<string> &re)
{
if(idx == n)
{
re.push_back(now);
return;
}
for(int i=idx;i<n;i++)
{
if(H[i+1] == 1 && dict.find(s.substr(idx, i-idx+1)) != dict.end() )
{
string new_now;
if(now == "")
new_now = s.substr(idx, i-idx+1);
else
new_now = now + " " + s.substr(idx, i-idx+1);
backtrack(s, new_now, i+1, H, n, dict, re);
}
}
}
};