【LeetCode】word break I && II

来源:互联网 发布:均线策略 优化 编辑:程序博客网 时间:2024/04/30 01:05

参考链接

http://www.cnblogs.com/xinsheng/p/3441044.html
http://www.cnblogs.com/xinsheng/p/3441154.html

http://blog.csdn.net/doc_sgl/article/details/12323015 递归过程中加记忆功能


http://blog.csdn.net/feliciafay/article/details/18999903


http://blog.csdn.net/a83610312/article/details/12870501 这个思路和上面的略不一样

题目描述


Word Break

 

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".






Word Break II

 

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"].



题目分析

思路:

1. DFS 搜索会 TLE

2. 改用 DP, 思路与 word palindrome 一样, iteration based dp 

3. bool dp[i] 表示从 i...s.size() 是否匹配

总结:

1. DP 解法中, 设置 dp[s.size()] = true 相当于初始条件


代码示例

class Solution {public:    bool dp[1000];    bool wordBreak(string s, unordered_set<string> &dict) {        memset(dp, false, sizeof(dp));        if(s.size() == 0 )            return true;        dp[s.size()] = true;        for(int i = s.size()-1; i >= 0; i --) {            int len1 = s.size() - i;            for(unordered_set<string>::iterator it_set = dict.begin(); it_set != dict.end(); it_set++) {                int len2 = it_set->size();                if(len1 >= len2 && dp[i] == false) {                    if(dp[i+len2] && s.substr(i, len2)==*it_set) {                        dp[i] = true;                        break;                    }                }            }        }        return dp[0];    }};
上面那个示例是遍历字典进行匹配。复杂度为O(s.size*dict.size)

下面的是先取子串再去字典中匹配。
class Solution {public:    bool wordBreak(string s, unordered_set<string> &dict) {   //bool wordBreak(string s, set<string> &dict) {       vector<bool> dp(s.size()+1,false);       dp[0] = true;       for(int i = 1;i<=s.size();i++)       {       if(dp[i-1])       {       int idx = i-1;       for(int j = idx;j<s.size();j++)       {       string str = s.substr(idx,j-idx+1);       if(dict.find(str) != dict.end())       dp[j+1] = true;   }       }   }   return dp[s.size()];}};



思路:

1. dp + 打印路径

2. dfs + 打印路径 是非常直接的, 设置一个全局变量记录当前路径, 当 dfs 到最后一步时输出该全局变量即可. 实现时要注意全局变量的 do 和 undo 操作. word break 使用 dfs 搜索超时了, 我就没用 dfs + 打印路径的方法来求解 word break II

3. word break II 是在前一题的基础上加上路径打印即可. 我仍然使用了上一题的代码, 稍作修改. 加上了一个 vector<string> record[1000], 这个变量记录可以使 dp[i] 为 true 的单词. 最后用一个 dfs 把这些单词摘下来组成句子

总结:

1. 第一次做 dp + 打印路径. 以前总是用搜索+打印路径来做类似的题目

2. 明显的搜索问题应当优先考虑 DP 解法

class Solution {public:    //vector<string> wordBreak(string s, unordered_set<string> &dict) {   vector<string> wordBreak(string s, set<string> &dict) {   int size = s.size();   vector<string> ret;       vector<vector<string> > vec(size,vector<string>());   vector<bool> dp(s.size()+1,false);      //printf("%d\n",vec.size());          dp[0] = true;       for(int i = 1;i<=s.size();i++)       {       //printf("%d-%d\n",i-1,(int)dp[i-1]);       if(dp[i-1])       {       int idx = i-1;       for(int j = idx;j<s.size();j++)       {       string str = s.substr(idx,j-idx+1);       if(dict.find(str) != dict.end())       {       dp[j+1] = true;  vec[idx].push_back(str);//////////////////////////////       }   }          }   }   //printf("%d-%d\n",s.size(),(int)dp[s.size()]);   if(dp[s.size()])   {   string tmp;   DFS(ret,vec,0,"",s);   }      return ret;}void DFS(vector<string> &ret,vector<vector<string> > &vec,int idx,string tmp,const string &s)//tmp不能使用引用 {//printf("idx = %d-------------%d\n",idx,s.size());if(idx == s.size()){//cout<<"tmp = "<<tmp<<endl;tmp.erase(tmp.size()-1,1);//去除最后一个空格 //cout<<"tmp = "<<tmp<<endl;ret.push_back(tmp);///////////////////tmp不能使用引用 return;}else if(idx > s.size())return;for(int i = 0;i<vec[idx].size();i++){//cout<<vec[idx][i]<<endl;int len = vec[idx][i].size(); tmp = tmp + vec[idx][i] + " ";DFS(ret,vec,idx+len,tmp,s);tmp.erase(tmp.size()-len-1,len+1);}}};



推荐学习C++的资料

C++标准函数库
http://download.csdn.net/detail/chinasnowwolf/7108919
在线C++API查询
http://www.cplusplus.com/
0 0
原创粉丝点击