LC-140 Word Break II

https://leetcode.com/problems/word-break-ii/

给一个字符串s,和一个字符串数组wordDict。现在要用空格把s分隔开,并且保证分割之后的每一部分都可以在wordDict中找到。以字符串数组的形式返回所有的可能分割方式。

例如s = "catsanddog"

wordDict = ["cat", "cats", "and", "sand", "dog"]

则返回结果为:["cat sand dog", "cats and dog"]

 

深度优先搜索:

从字符串头部开始匹配,使用start变量表示当前匹配的位置。对字典中的每个词在start处进行匹配,如果匹配到了,则记录下该词的下标,然后开始下一层搜索。如果字典中所有词都没有匹配到,则从start处开始没有正确答案。

当开始新的一层搜索时发现start已经走完了整个字符串,说明此时整个字符串s都已经被分配成了字典中的词,利用之前记录的更新到这个状态时所有的字典词的下标,更新结果。

这里我做了一个记忆化,利用Results二维数组存储结果,Results[start]表示了从start处开始所有可以匹配的上的字典里词的下标。如果从start处开始无解,则将Results[start]标记为-1,这样可以快速返回无解的信息,防止重复搜索(不对无解情况进行剪枝的话将会超时)

 1 class Solution {
 2   public:
 3     vector<vector<int>> Results;
 4     vector<int> WordsInDict;
 5     vector<string> ret;
 6 
 7     bool DFS(string &s, vector<string> &wordDict, int start) {
 8         if (start >= s.length()) {
 9             // all the sentence was allocated into wordDict
10             string NewRet = wordDict[WordsInDict[0]];
11             for (int i = 1; i < WordsInDict.size(); i++) {
12                 NewRet += " " + wordDict[WordsInDict[i]];
13             }
14             ret.push_back(NewRet);
15             return true;
16         }
17 
18         if (Results[start].size()) {
19             // the result of start has already been calculated
20             if (Results[start][0] < 0) {
21                 // start has no valid result
22                 return false;
23             } else {
24                 int ResultsLen = Results[start].size();
25                 for (int i = 0; i < ResultsLen; i++) {
26                     int DictWordIndex = Results[start][i];
27                     WordsInDict.push_back(DictWordIndex);
28                     DFS(s, wordDict, start + wordDict[DictWordIndex].length());
29                     WordsInDict.pop_back();
30                 }
31                 return true;
32             }
33         } else {
34             // the result has not yet been calculated, do the DFS
35             int DictLen = wordDict.size();
36             bool HasValidResult = false;
37             for (int i = 0; i < DictLen; i++) {
38                 if (string(s, start, wordDict[i].length()) == wordDict[i]) {
39                     WordsInDict.push_back(i);
40                     bool ok = DFS(s, wordDict, start + wordDict[i].length());
41                     WordsInDict.pop_back();
42                     if (ok) {
43                         Results[start].push_back(i);
44                         HasValidResult = true;
45                     }
46                 }
47             }
48             if (!HasValidResult)
49                 Results[start].push_back(-1);
50             return HasValidResult;
51         }
52     }
53 
54     vector<string> wordBreak(string s, vector<string> &wordDict) {
55         int len = s.length();
56         for (int i = 0; i < len; i++) {
57             vector<int> v;
58             Results.push_back(v);
59         }
60         DFS(s, wordDict, 0);
61 
62         return ret;
63     }
64 };
代码

 

posted @ 2020-05-29 10:18  Osoii  阅读(172)  评论(0)    收藏  举报