惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
爱范儿
爱范儿
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
博客园 - 聂微东
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
T
Tailwind CSS Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
罗磊的独立博客
Jina AI
Jina AI

博客园 - 来自海边的一片云

Binary Tree Maximum Path Sum 解题注意 CodingTMD’s Reading List De Bruijn 序列生成 Word Ladder I ,II 解题思路 suduko及8皇后问题及相关问题的解题思路 Search for a string in an infinite stream of input string. 内存管理 Permutations leetcode Clone Graph leetcode 开弓没有回头箭 combination sum leetcode Combinations leetcode 组合问题 word break leetcode LRU cache Leetcode 重新试着写blog SQL injection Fuzz testing XML库的解析效率 Init()
leetcode Word Break II 解题思路
来自海边的一片云 · 2014-02-16 · via 博客园 - 来自海边的一片云

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

这题有两种常见的解法。

1.DFS

1.先找字符串的前缀,找到一个前缀,然后把这个前缀放到路径里面,

2.然后对剩下的字符串,再重复第一步。

直到字符串搜索结束。

其中还有个trick是,如果字符串的前缀不会超过字典里最长的字符串长度。

这个方法能够应付一般的情况,但是在leetcode上最复杂的case时候会超时。。。。

2. 动态规划

这个做法其实是第一题的变形。但是这个变形很巧妙。这个思路说了也很直接。但是也很巧妙。

先回忆一下,第一题work break是怎么做的。在字符串位置为I处,判断此I是不是wordbreakable,

1. 那么从字符串头上开始,找wordbreakbale的位置k,然后检查这个K和I之间的子字符串是不是在字典里

2.如果在字典里,那么位置I是wordbreakable的。

3.如果不在字典里,那么继续往前找,直到K到I 位置,那么这个I肯定不是wordbreakable的。

在结束的时候

直接查wordbreak[N]就是结果。

但是路径信息完全没有保留下来。

比如catsanddog,  cat|s|and|dog|

其中|为该位置可以分割,但是如果直接拿这个wordbreakable 标记数组来切词,肯定不对,比如s就不在字典里面。

那怎么做呢?考虑到图的adj 那就也可以搞一个类似的结构。

0

1     c   NULL

2     a   NULL

3     t     0

4     s    0

5     a    NULL

6     n    NULL

7     d    3,4 

8     d   NULL

9     o   NULL

10   g    7

然后从最后一个字符开始做一个遍历就搞定了。

void backtrack(string s, vector<list<int>>& lookup, int index, vector<string>& result, vector<string> path)
    {
        if (index == 0)//reach the end 
        {
            string str;
            int size = path.size();
            for (int i =size - 1; i >= 0; i--)
            {
                str.append(path[i]);
                if (i!=0)str.append(" ");
                
            }
            result.push_back(str);
            return;
        }
    
        list<int>::iterator it = lookup[index].begin();
        for (; it != lookup[index].end(); it++)
        {
            int prev = *it;
            path.push_back(s.substr(prev, index - prev));
            backtrack(s, lookup, prev, result, path);
            path.pop_back();
        }
    
    
    }
    
    vector<string> wordBreak(string s, unordered_set<string> &dict) {
    
        int size = s.length();
        vector<bool> wordbreak(size + 1);
        vector<list<int>> lookup(size + 1);
        vector<string> result;
        vector<string> path;
        wordbreak[0] = true;
    
        for (int index = 1; index <= size; index++)
        {
            for (int prev = 0; prev<index; prev++)
            {
                if (wordbreak[prev] && dict.find(s.substr(prev, index - prev)) != dict.end())
                {
                    //found a match str
                    wordbreak[index] = true;
                    lookup[index].push_back(prev);
    
                }
            }
        }
        // here we got 
        // 1 . whether string breakable wordbreak[n], 
        // 2. lookup matrix like a graph
    
        if (!wordbreak[size]) return result;
    
        backtrack(s, lookup, size, result, path);
    
        return result;
    
    }