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

这题有两种常见的解法。

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;
    
    }

 

posted @ 2014-02-16 13:55  来自海边的一片云  阅读(400)  评论(0编辑  收藏  举报