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

动态规划,递归枚举

首先,确定一个字符串是否可以拆分,动态规划解决。

在面临要输出所有的可行解的时候,需要使用一个备忘录记录下每一步的前驱结点。(即记录下每个单词的前一个单词的位置)。因为前一个单词可能不唯一,最大的个数为n(总共n个位置)。

注:对于第i个位置而言,判断s[0...i]是否可分,如果该单词本身就在字典中,那么它的前驱index是-1,如果s[j ... i - 1]是一个合法的单词,并且s[0 ...  j - 1 ]也是合法的单词,那么它的前驱index应该是 j - 1 ,以此类推,每个位置的前驱节点的个数至多为n。由于上述出现了-1这个负数,那么我们定义s的下标从1开始。即下述“第i个字符”表示s[i-1].因此,定义二维数组备忘录tbl[n+1][n],其中tbl[i]表示第i个字符的所有的前驱结点的index的集合。


代码:

class Solution {
public:
    vector<string> wordBreak(string s, unordered_set<string> &dict)
    {
        vector<string> ret;
        if(s.empty())
            return ret;
        int len = s.length();
        vector<vector<int> > tbl(len + 1, vector<int>());
        GenerageTable(s, dict, tbl);
        string path;
        dfs(s, tbl, ret, path, len);
        return ret;
    }
    //创建tbl记录 记录所有以i点为结尾的分割的位置,如果不能那么tbl[i]为空,如果可以就记录起始位置的位置
    void GenerageTable(const string& s, unordered_set<string>& dict,
                       vector<vector<int> >& tbl)
    {
        int len = s.size();
        vector<bool> flag(len + 1, false);
        flag[0] = true;
        for (size_t i = 1; i <= len; ++i) {
            for (size_t j = 0; j < i; ++j) {
                if(flag[j] && dict.count(s.substr(j, i - j)) != 0)
                {
                    tbl[i].push_back(j);
                    flag[i] = true;
                }
            }
        }
    }
    //递归的寻找符合要求的字符串分割方法并将结果存入ret中
    void dfs(const string& s, vector<vector<int> >& tbl, vector<string>& ret, string& path, int step)
    {
        if(step == 0)
            ret.push_back(path);
        if (tbl[step].size()) {
            for(size_t i = 0; i < tbl[step].size(); ++i)//递归求解所有可以以step点结尾的分割
            {
                string tmp = path;
                if(!path.empty())
                    path = ' ' + path;//save the break word using space to seperate it.
                path = s.substr(tbl[step][i], step - tbl[step][i]) + path;
                dfs(s, tbl, ret, path, tbl[step][i]);
                path = tmp;//递归返回的时候回复path,进入下一次循环
            }
        }
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值