LeetCode140:Word Break II

mickole發表於2014-02-18

題目:

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

解題思路:

這道題是上一道題Word Break升級版,難度更大些,需要用DP+DFS解決

這裡採用DP中的自底向上實現,dp[i]表示前i個字元能否進行Wordbreak。當求解dp[i]時,可利用已經求解的dp[i-1],

dp[i-2]…dp[1],dp[0]進行求解。

對於dp[n]的求解,我們可以將n個字元進行切分求解,分為前i個字元和後n-i個字元,i可以為(0,1,2,3,4…n-1)

假設i為1時,可根據dp[i]和後面的n-1個字元組成的單詞是否在dict中來判斷dp[n],只要i(0,1,2,3,4…n-1)其中一種

情況為真,則dp[n]為true,表示可以進行workbreak。

因為本題需要重構結果,所以必須要有一個資料結構來儲存每段長度的切割方案,這裡我用unordered_map<int, vector<int> >進行儲存,key為字元長度,vector儲存該key對應的切割方案。

如何求得unordered_map<int, vector<int> >中的值呢?那就應該利用求解dp[i]時,每當有一種切割方案使得dp[i]為true時,將其對應的切割位置存放到i對應的vector中,待之後用於結果重構。

unordered_map<int, vector<int> >求得後,接下來是採用DFS演算法進行結果重構,如程式碼執行結果圖,當長度為10時,有一種切割方案,即在長度為7的位置進行切割,然後長度為7的切割方案又有兩種3和4,長度為3和4時,切割方案都為0,所以採用DFS時,遍歷順序為7,3,0然後獲得一種結果,之後回溯到7,4,因為4的切割方案為0,所以為7,4,0,又是一種結果。

實現程式碼:

#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
using namespace std;

/*
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"].
*/ 
class Solution {
public:
    vector<string>  wordBreak(string s, unordered_set<string> &dict) {
        vector<string> retvec;
        if(s.size() == 0 || dict.size() == 0)
            return retvec;
        int len = s.size();
        vector<bool> dp(len+1, false);//儲存狀態,dp[i]表示前i個字元是否可以進行wordBread
        unordered_map<int, vector<int> > hash_map;// 存放使得dp[i]為true的切割方案 
        dp[0] = true;
        for(int i = 1; i <= len; i++)
        {
            vector<int> vec;
             for(int j = 0; j < i; j++)
            {                
                if(dp[j] && dict.count(s.substr(j, i-j)) == 1)//對前i個字元進行切分時,只要有一種情況為true,則dp[i]=true 
                {
                    dp[i] = true;
                    vec.push_back(j);//放使得dp[i]為true的切割方案 
                }            
            }
            hash_map[i] = vec;           
        }

            
        for(int k = 1; k <= len; k++)
        {
            vector<int> tvec = hash_map[k];
            cout<<k<<":";
            vector<int>::iterator iter;
            for(iter = tvec.begin(); iter != tvec.end(); ++iter)
            {
                cout<<*iter<<" ";         
            }
            cout<<endl;
        }
        
        vector<int> curVec;
        getResult(hash_map, s, len, retvec, curVec);
        return retvec;
        
    }
    
    //採用DFS解決 
    void getResult(unordered_map<int, vector<int> > &hash_map,string s, int len, vector<string> &retvec, vector<int> &curVec)
    {
        if(len == 0)
        {
            string t;
            int start = 0;
            for(int i = curVec.size()-2; i >= 0; i--)
            {
                int c = curVec[i];
                t += s.substr(start, c-start);
                t += " ";
                start = c;               
            }
            t += s.substr(curVec[0]);
            retvec.push_back(t);
            return ;            
        }
        vector<int> tvec = hash_map[len];
        vector<int>::iterator iter;
        for(iter = tvec.begin(); iter != tvec.end(); ++iter)
        {
            curVec.push_back(*iter);
            getResult(hash_map, s, *iter, retvec, curVec);
            curVec.pop_back();           
        }
        
    }
      
};

int main(void)
{
    string s("catsanddog");
    unordered_set<string> dict;
    dict.insert("cat");
    dict.insert("cats");
    dict.insert("and");
    dict.insert("sand");
    dict.insert("dog");

    Solution solution;
    vector<string> retvec = solution.wordBreak(s, dict);
    vector<string>::iterator iter;
    for(iter = retvec.begin(); iter != retvec.end(); ++iter)
        cout<<*iter<<endl;


    return 0;
}

執行結果:

image

相關文章