zoukankan      html  css  js  c++  java
  • LeetCode140: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"].

    解题思路:

    这道题是上一道题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

  • 相关阅读:
    Java 水仙花数
    Java 手机短号
    Java发工资
    VMware安装Linux CentOS7
    (转载)MongoDB的学习--explain()和hint()
    Linux基本操作练习题整理
    Linux的安装配置及常用命令(二)
    Linux的安装配置及常用命令(一)
    java中Json的使用
    Ajax
  • 原文地址:https://www.cnblogs.com/mickole/p/3673296.html
Copyright © 2011-2022 走看看