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

Thanks to:https://discuss.leetcode.com/topic/12997/11ms-c-solution-concise

不能理解自己为什么反复TLE…

可能是数据又被加强了吧…

这道题可以用2维的区间DP去做,令DP[i][j]表示i~j为回文,则d[i][j]=dp[i][k] & dp[k+1][j]

然后发现其实这样是没有必要的,因为set查询复杂度是O(1),所以求取dp[i][k]的复杂度并不高,所以不需要另开一维。

于是一维就够了,dp[i]表示0~i是否是想要的字符串;

两重循环就可以做出,类似上一题,然后进行递归获取全解。。。

然而就是这样一直TLE…

究其原因可能是DP+回溯用了太多时间,

而参考的方法直接存储了子元素的解…这样成功地阻止了对某一解的反复求取…

很强。。。佩服

他是从后往前求取值,生成一个前缀数组,每次加上后缀。

这样仅仅通过递归即可解决。

使用了map来存储一个字符串的解,很强…

class Solution {
public:
    unordered_map<string, vector<string>> m;
    vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
        //找出一个字符串已经存在的匹配vector
        if(m.count(s)) return m[s];
        int n=s.size();
        vector<string> result;
        
        if(wordDict.find(s)!=wordDict.end())
        result.push_back(s);
        
        for(int i=1;i<n;i++){
            string suffix=s.substr(i);
            if(wordDict.count(suffix)){
                //取前一部分字符串
                string temp=s.substr(0,i);
                vector<string> suffpre=merge(suffix,wordBreak(temp,wordDict));
                result.insert(result.end(),suffpre.begin(),suffpre.end());
            }
        }
        m[s]=result;
        return result;
    }
    
    //添加后缀
    vector<string> merge(string suffix,vector<string> pre){
        for(int i=0;i<pre.size();i++){
            pre[i]+=" "+suffix;
        }
        return pre;
    }
};

自己的方法虽然超时,但是还是贴一下供之后自己查阅

    
    //这个方法依然会超时
    // int n;
    // string s;
    // unordered_set<string> wordDict;
    // bool dp[1000][1000];
        // int n=s.size();
        // this->n=n;
        // this->s=s;
        // this->wordDict=wordDict;
        // vector<string> result;
        // //所以昨天一开始自己的直觉的对的,是区间DP,而上一题所用应当是压缩一维之后的
        // // bool dp[n][n];
        // memset(dp,0,sizeof(dp));
        // for(int len=1;len<=n;len++){
        //     for(int i=0;i<n && len+i-1<n;i++){
        //         int j=len+i-1;
                
        //         //获取当前对应的子字符串
        //         dp[i][j]=wordDict.find(s.substr(i,j-i+1))!=wordDict.end();
        //         // //判断dp[i][j]和 dp[i][k] & dp[k+1][j]
        //         // for(int k=i;k<j && !dp[i][j];k++){
        //         //     dp[i][j]=dp[i][k] && dp[k+1][j];
        //         // }
        //     }
        // }
        // //得到dp矩阵
        // // for(int i=0;i<n;i++){
        // //     for(int j=0;j<n;j++){
        // //         printf("%d ",dp[i][j]);
        // //     }
        // //     printf("\n");
        // // }
        // // printf("\n");
        // //dp[0][n-1]为所求解
        // string temp="";
        // generate(temp,n-1,result);
        // return result;
    // void generate(string temp,int start,vector<string> &result){
        
    //     if(start==n){
    //         result.push_back(temp);
    //         return;
    //     }
        
    //     for(int i=0;i<=start;i++){
    //         if(dp[i][start]){
    //             string pre=temp;
    //             if(temp==""){
    //                 temp=s.substr(i,start-i+1);
    //                 generate(temp,i-1,result);
                    
    //             }
    //             else{
    //                 temp=temp+" "+s.substr(i,start-i+1);
    //                 generate(temp,i-1,result);
    //             }
    //             // temp=pre;
    //         }
    //     }
    // }
    
    //超时
    // void generate(vector<string> &temp,int start,int size,vector<string> &result){
    //     if(start==n){
    //         //将temp里的元素汇集成一个string推到result里
    //         string final="";
    //         for(int i=0;i<temp.size();i++){
    //             if(i==0) final=temp[i];
    //             else final=final+" "+temp[i];
    //         }
    //         result.push_back(final);
    //         return;
    //     }
        
    //     for(int i=start;i<n;i++){
    //         //这个位置可以构成解
    //         if(dp[i+1]){
    //             string t=s.substr(start,i-start+1);
    //             //首先t必须在字典里
    //             if(wordDict.find(t)==wordDict.end()) continue;
    //             //size表示temp数组里元素的总长
    //             //要求当前到达的总长必须为遍历到的串总长
    //             if(size+t.size()==i+1){
    //                 temp.push_back(t);
    //                 generate(temp,i+1,i+1,result);
    //                 temp.pop_back();
    //             }
    //         }
    //     }
    // }

点赞