139. 单词拆分 (记忆化dfs)
难度中等
给你一个字符串 s
和一个字符串列表 wordDict
作为字典,判定 s
是否可以由空格拆分为一个或多个在字典中出现的单词。
说明:拆分时可以重复使用字典中的单词。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"] 输出: true 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"] 输出: true 解释: 返回 true 因为"
applepenapple"
可以被拆分成"
apple pen apple"
。 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false
提示:
1 <= s.length <= 300
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 20
s
和wordDict[i]
仅有小写英文字母组成wordDict
中的所有字符串 互不相同
记忆化 DFS
class Solution: def wordBreak(self, s: str, wordDict: List[str]) -> bool: wordSet = set(wordDict) memo = {} def backtrack(s, start, wordSet): if start in memo: return memo[start] if start == len(s): memo[start] = True return True for end in range(start + 1, len(s) + 1): if s[start:end] in wordSet and backtrack(s, end, wordSet): memo[start] = True return True memo[start] = False return False return backtrack(s, 0, wordSet)
class Solution { public: bool dfs(vector<int>& memo,int start,string& s, unordered_set<string>& word_set) { if (start >= s.size()) { return true; } if (memo[start]!=-1) return memo[start]; for(int i = start; i < s.size();i++) { string w = s.substr(start, i-start+1); if (word_set.find(w) != word_set.end() && dfs(memo,i+1,s,word_set)) { memo[start] = 1;// true return true ; } } memo[start] = 0;// false return false; } bool wordBreak(string s, vector<string>& wordDict) { unordered_set<string> word_set; for(auto word :wordDict) { word_set.insert(word); } vector<int> memo = vector<int>(s.size(),-1); return dfs(memo,0,s,word_set); } };
class Solution { public: bool wordBreak(string s, vector<string>& wordDict) { vector<bool>dp(s.size()+1,false); dp[0] = true; for(int j = 1;j <=s.size();j++) { for(int i = 0;i<wordDict.size();i++) { auto word = wordDict[i]; int word_len = word.size(); if(j-word_len>=0 && s.substr(j-word_len,word_len)==word) { dp[j] = dp[j] || dp[j-word_len]; } } } return dp[s.size()]; } };