# [139. Word Break](https://leetcode.com/problems/word-break/) # 思路 ## 思路一 DFS 此题最好想的就是用hashset记录词典以加快查找速度, 再用一个DFS即可解决. 但由于DFS里面存在很多重复计算, 所以计算复杂度很高, 亲测是会超时的. 为了避免这些重复计算, 我们可以用一个长度和字符串s等长的数组cache(初始化全为-1)来记录之前已经计算的过程.其中cache[i]=1表示s[i,i+1,...]是一个 可以拆开的字符串, 则cache[i]=0表示s[i,i+1,...]是一个拆不开的字符串.然后就可以DFS了, 我们假设s[0, 1,..., start-1]是可以拆开的, DFS函数 的内容就是判断从start开始的s的子串是否可以拆开, 那么DFS函数可以这样组织: * 如果start到达末尾了, 那即可返回true; * 如果cache[start]不为-1, 说明之前计算过从start开始的子串是否可以拆开, 所以直接返回cache的结果即可; * 否则就需要进行循环递归了, 得到结果后需要对cache[start]写入合适的值. ## 思路二 动态规划 思路一使用了cache数组, 就有点动态规划的意思了. 这里我们使用一个长度为s长度加一的dp数组, 将dp最后一个值初始化为1其他全部初始化为0, 意义和思路一中cache代表的意义一样. 那么我们就可以从后往前开始遍历并进行和思路一同样的动归了. # C++ ## 思路一 ``` C++ class Solution { private: bool DFS(string &s, int start, unordered_set&dict, vector&cache){ if(start == s.size()) return true; if(cache[start] != -1) return cache[start]; for(int i = start; i < s.size(); i++){ if(dict.count(s.substr(start, i - start + 1)) && DFS(s, i + 1, dict, cache)){ cache[start] = 1; return true; } } cache[start] = 0; return false; } public: bool wordBreak(string s, vector& wordDict) { unordered_setdict(wordDict.begin(), wordDict.end()); vectorcache(s.size(), -1); return DFS(s, 0, dict, cache); } }; ``` ## 思路二 ```C++ public: bool wordBreak(string s, vector& wordDict) { unordered_setdict(wordDict.begin(), wordDict.end()); vectordp(s.size() + 1, 0); dp[s.size()] = 1; for(int start = s.size(); start >= 0; start--){ for(int i = start; i < s.size(); i++){ if(dp[i+1] && dict.count(s.substr(start, i-start+1))){ dp[start] = 1; break; } } } return dp[0] == 1; } }; ```