【LeetCode】word break I && II

參考鏈接

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/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++標準函數庫
在線C++API查詢
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章