• 【Word Break II】cpp


    题目:

    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>& wordDict)
            {
                vector<string> ret;
                vector<string> tmp;
                vector<bool> possible(s.size(), true);
                Solution::dfs( possible, wordDict, ret, tmp, s, 0, s.size()-1);
                return ret;
            }
            static void dfs( 
                vector<bool>& possible, // possible[i] : if s[i~end] can be possible word broken 
                unordered_set<string>& wordDict, 
                vector<string>& ret, 
                vector<string>& tmp, 
                string& s, int begin, int end )
            {
                if ( begin>end )
                {
                    string str = "";
                    for ( int i=0; i<tmp.size(); ++i ) { str = str + tmp[i] + " "; }
                    ret.push_back(str.substr(0,str.size()-1));
                }
                for ( int i=begin; i<=end; ++i )
                {
                    if ( wordDict.find(s.substr(begin,i-begin+1))!=wordDict.end() && possible[i] )
                    {
                        tmp.push_back(s.substr(begin,i-begin+1));
                        int oriSolution = ret.size();
                        Solution::dfs( possible, wordDict, ret, tmp, s, i+1, end);
                        if ( oriSolution==ret.size()) possible[i]=false;
                        tmp.pop_back();
                    }
                }
            }
    };

    tips:

    其实在word break i这道题的时候就想用dfs做,但是会超时。

    word break ii这道题是求所有可行解,就尤其想用dfs来做。

    一开始写了一版裸dfs的代码,发现会超时:原因是没有剪枝。

    这里学习了一下大神的剪枝技巧(http://fisherlei.blogspot.sg/2013/11/leetcode-wordbreak-ii-solution.html

    这里的possible[i] 代表的是 s[i+1:s.size()-1] 可否被给定的wordDict来word break。翻译过来就是,从i往后(不包括i)是否行可以被wordDict表示。

    这个思路很精妙:

    1. 从给定当前点往后看,看能否满足条件。这样dfs下次再走到这个点的时候,就知道是否可以往下走了。

    2. 为什么不把possible[i]当成s[0~i]是否满足条件呢?因为能来到位置i的方式有很多种,一种方式行不通不代表其他方式行不通

    3. 由i往后,一直到end,已经把所有可能走到最后的方式都包括了,如果所有可能走到最后的方式中都行不通,那就是肯定行不通了

    4. 如何记录是否行得通了呢?我就是卡在这里了,没想到太好的办法。这时学习了大神的办法,比较下解集的个数:如果个数没变,那肯定是行不通了。

    ===============================================

    第二次过这道题,复习遍原来的方法。

    class Solution {
    public:
        vector<string> wordBreak(string s, unordered_set<string>& wordDict)
        {
            vector<string> ret;
            vector<string> tmp;
            vector<bool> possible(s.size(),true);
            Solution::dfs(ret, tmp, 0, s.size()-1, s, wordDict, possible);
            return ret;
        }
        static void dfs(
            vector<string>& ret,
            vector<string>& tmp, 
            int begin,
            int end,
            string& s,
            unordered_set<string>& wordDict,
            vector<bool>& possible
            )
        {
            if ( begin>end )
            {
                string str = "";
                for ( int i=0; i<tmp.size(); ++i ) str += tmp[i] + " ";
                ret.push_back(str.substr(0,str.size()-1));
                return;
            }
            for ( int i=begin; i<=end; ++i )
            {
                if ( wordDict.find(s.substr(begin, i-begin+1))!=wordDict.end() && possible[i] )
                {
                    tmp.push_back(s.substr(begin, i-begin+1));
                    int pre = ret.size();
                    Solution::dfs(ret, tmp, i+1, end, s, wordDict, possible);
                    if ( ret.size()==pre ) possible[i] = false;
                    tmp.pop_back();
                }
            }
        }
    };
  • 相关阅读:
    欧拉计划之题目2:在斐波那契数列中,找出4百万以下的项中值为偶数的项之和。
    MFC非模态对话框的销毁
    MFC:只允许产生一个应用程序实例的具体实现
    从_tiddata看CRT的线程不安全函数
    关于消息循环的深入分析
    MFC:关于MFC窗口对象(CWnd对象)与Window对象(HWND所指对象)的销毁问题
    使用FindFirstFile和FindNextFile对给定目录下所有文件进行广度优先遍历
    工作线程的消息循环与通信
    MFC和设计模式
    _endthreadex与CloseHandle
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4553674.html
Copyright © 2020-2023  润新知