这道题思路不难想,但是代码却改了好几次才通过,最主要的问题是会出现超时间/超内存
    第一种方式:
    利用动态规划—超时间限制,因为有很多没有利用到的状态也被计算了,这些状态也都被计算了下来

    1. class Solution {
    2. public:
    3. vector<string> wordBreak(string s, vector<string>& wordDict) {
    4. int n = s.size();
    5. vector<vector<vector<string>>> dp(n, vector<vector<string>>(n));
    6. for(int len = 1; len <= n; len++)
    7. {
    8. for(int l = 0; l < n; l++)
    9. {
    10. int r = l + len - 1;
    11. if(r >= n) break;
    12. string sub = s.substr(l, r - l + 1);
    13. if(find(wordDict.begin(), wordDict.end(), sub) != wordDict.end())
    14. {
    15. dp[l][r].push_back(sub);
    16. }
    17. for(int k = l; k < r; k++)
    18. {
    19. if(dp[l][k].size() && dp[k + 1][r].size())
    20. {
    21. for(auto x: dp[l][k])
    22. for(auto y: dp[k+1][r])
    23. {
    24. string tmp = x + " " + y;
    25. dp[l][r].push_back(tmp);
    26. }
    27. }
    28. }
    29. }
    30. }
    31. vector<string> res;
    32. sort(dp[0][n - 1].begin(), dp[0][n - 1].end());
    33. for(auto x: dp[0][n - 1])
    34. {
    35. if(!res.size() || x != res.back())
    36. res.push_back(x);
    37. }
    38. return res;
    39. }
    40. };

    dp—超内存限制 原因是到最后了才发现最后面的拼不起来啊,那个恨,前面的都浪费了

    1. class Solution {
    2. public:
    3. vector<string> wordBreak(string s, vector<string>& wordDict) {
    4. int n = s.size();
    5. vector<vector<string>> dp(n);
    6. for(int i = 0; i < s.size(); i++)
    7. {
    8. string sub = s.substr(0, i - 0 + 1);
    9. if(find(wordDict.begin(), wordDict.end(), sub) != wordDict.end())
    10. {
    11. dp[i].push_back(sub);
    12. }
    13. for(int j = i; j > 0; j--)
    14. {
    15. string sub = s.substr(j, i - j + 1);//[j, i]
    16. if(find(wordDict.begin(), wordDict.end(), sub) != wordDict.end() && dp[j - 1].size())
    17. {
    18. for(auto x: dp[j - 1])
    19. {
    20. dp[i].push_back(x + " " + sub);
    21. }
    22. }
    23. }
    24. }
    25. return dp[n - 1];
    26. }
    27. };

    dfs—先扫一次到最后看看能不能拼起来,如果能拼起来再拼起来,并且可以去利用set加快搜索速度

    1. class Solution {
    2. string s;
    3. set<string> wordDict;
    4. map<int, vector<string>> mp;
    5. vector<int> v;
    6. void dfs(int start)
    7. {
    8. if(start == s.size())
    9. {
    10. v[start] = 1;
    11. mp[start] = {""};
    12. return;
    13. }
    14. if(v[start] != -1)//说明已经访问过了
    15. {
    16. return;
    17. }
    18. vector<string> res;
    19. for(int k = start; k < s.size(); k++)
    20. {
    21. string sub = s.substr(start, k - start + 1);
    22. if(wordDict.count(sub))
    23. {
    24. dfs(k + 1);
    25. if(v[k+1] == 0) continue;
    26. for(auto x: mp[k+1])
    27. {
    28. if(x.size())
    29. res.push_back(sub + " " + x);
    30. else
    31. res.push_back(sub);
    32. }
    33. }
    34. }
    35. if(res.size())
    36. {
    37. v[start] = 1;
    38. mp[start] = res;
    39. }
    40. else
    41. {
    42. v[start] = 0;
    43. }
    44. return;
    45. }
    46. public:
    47. vector<string> wordBreak(string _s, vector<string>& _wordDict) {
    48. s = _s;
    49. for(auto x:_wordDict)
    50. wordDict.insert(x);
    51. v = vector<int>(s.size() + 1, -1);//-1没有搜索, 0 不行 1可以
    52. dfs(0);
    53. vector<string> tmp = mp[0];
    54. if(tmp.size())
    55. return tmp;
    56. else
    57. return vector<string>();
    58. }
    59. };

    第二次写题

    1. class Solution {
    2. vector<vector<string>> res;//这里相当于保存记录,防止多次调用
    3. vector<int> mask;//这里相当于记录这个idx开始的是否被访问过
    4. set<string> st;
    5. void dfs(string s, int idx)
    6. {
    7. if(idx == s.size()) return;
    8. for(int i = idx; i < s.size(); i++)
    9. {
    10. string str = s.substr(idx, i - idx + 1);
    11. if(st.find(str) != st.end())
    12. {
    13. //这里有意思,这里可以实现先后面的
    14. if(mask[i + 1] == -1) dfs(s, i + 1);
    15. //然后再回来这里进行拼接
    16. for(auto x: res[i + 1])
    17. {
    18. //这里有两种情况,因为如果是最后就不用加' '
    19. if(x != "")
    20. res[idx].push_back(str + ' ' + x);
    21. else
    22. res[idx].push_back(str);
    23. }
    24. }
    25. }
    26. //做一下标记,这个idx已经被找过了
    27. mask[idx] = 1;
    28. }
    29. public:
    30. vector<string> wordBreak(string s, vector<string>& wordDict) {
    31. if(!s.size()) return vector<string>();
    32. res.resize(s.size() + 1);
    33. res[s.size()]= {""};
    34. mask.resize(s.size() + 1, -1);
    35. mask[s.size()] = 1;
    36. for(auto x: wordDict)
    37. {
    38. if(st.find(x) == st.end())
    39. st.insert(x);
    40. }
    41. //下面这里是想看有没有在s出现的字母没有出现在wordDict里面
    42. //如果在s出现在wordDict没有出现,那肯定匹配不上
    43. set<char> worddic;
    44. set<char> word;
    45. for(auto x: s)
    46. {
    47. if(word.find(x) == word.end())
    48. word.insert(x);
    49. }
    50. for(auto x: st)
    51. {
    52. for(auto c: x)
    53. {
    54. if(worddic.find(c) == worddic.end())
    55. worddic.insert(c);
    56. }
    57. }
    58. for(auto x: word)
    59. {
    60. if(worddic.find(x) == worddic.end())
    61. return vector<string>();
    62. }
    63. //dfs
    64. dfs(s, 0);
    65. //返回 res是二维的,所以这里返回的是第一个
    66. return res[0];
    67. }
    68. };

    第三次写题

    1. class Solution {
    2. vector<vector<string>> res;
    3. vector<bool> mask;
    4. set<string> dict;
    5. void dfs(string s, int idx)
    6. {
    7. if(idx >= s.size()) return;
    8. if(mask[idx] == false) return;
    9. mask[idx] = false;
    10. for(int i = idx; i < s.size(); i++)
    11. {
    12. string str = s.substr(idx, i - idx + 1);
    13. if(dict.find(str) == dict.end()) continue;
    14. dfs(s, i + 1);
    15. for(auto x: res[i + 1])
    16. {
    17. string ns = str + (x==""? "":' '+x);
    18. res[idx].push_back(ns);
    19. }
    20. }
    21. }
    22. public:
    23. vector<string> wordBreak(string s, vector<string>& wordDict) {
    24. if(!s.size()) return vector<string>();
    25. res.resize(s.size() + 1);
    26. mask = vector<bool>(s.size() + 1, true);
    27. res[s.size()] = {""};
    28. mask[s.size()] = false;
    29. for(auto w: wordDict)
    30. {
    31. if(dict.find(w) == dict.end())
    32. dict.insert(w);
    33. }
    34. dfs(s, 0);
    35. return res[0];
    36. }
    37. };

    需要注意的是加了一段利用char来先筛选的,会让使用的内存数量减小,从17.2M->13.2M

    class Solution {
        vector<vector<string>> res;
        vector<bool> mask;
        set<string> dict;
        void dfs(string s, int idx)
        {
            if(idx >= s.size()) return;
            if(mask[idx] == false) return;
            mask[idx] = false;
            for(int i = idx; i < s.size(); i++)
            {
                string str = s.substr(idx, i - idx + 1);
                if(dict.find(str) == dict.end()) continue;
                dfs(s, i + 1);
                for(auto x: res[i + 1])
                {
                    string ns = str + (x==""? "":' '+x); 
                    res[idx].push_back(ns);
                }
            }
        }
    
    public:
        vector<string> wordBreak(string s, vector<string>& wordDict) {
            if(!s.size()) return vector<string>();
            res.resize(s.size() + 1);
            mask = vector<bool>(s.size() + 1, true);
            res[s.size()] = {""};
            mask[s.size()] = false;
            for(auto w: wordDict)
            {
                if(dict.find(w) == dict.end())
                    dict.insert(w);
            }
            //和上面的比,加了这一段
            set<char> worddic;
            set<char> word;
            for(auto x: s)
            {
                if(word.find(x) == word.end())
                    word.insert(x);
            }
            for(auto x: dict)
            {
                for(auto c: x)
                {
                    if(worddic.find(c) == worddic.end())
                        worddic.insert(c);
                }
            }
            for(auto x: word)
            {
                if(worddic.find(x) == worddic.end())
                    return vector<string>();
            } 
            //
            dfs(s, 0);
            return res[0];
        }
    };