[LeetCode] 140. Word Break II 单词拆分II
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.
Note:
- The same word in the dictionary may be reused multiple times in the segmentation.
- You may assume the dictionary does not contain duplicate words.
Example 1:
catsanddog
["cat", "cats", "and", "sand", "dog"]
[
"cats and dog",
"cat sand dog"
]
Example 2:
Input: s = "pineapplepenapple" wordDict = ["apple", "pen", "applepen", "pine", "pineapple"] Output: [ "pine apple pen apple", "pineapple pen apple", "pine applepen apple" ] Explanation: Note that you are allowed to reuse a dictionary word.
Example 3:
Input: s = "catsandog" wordDict = ["cats", "dog", "sand", "and", "cat"] Output: []
139. Word Break 的拓展,那道题只是让判断是否可以拆分,而这道题要求输出所有可能的拆分组合。
解法:dp + dfs,先用dp计算是否可以拆分,然后用dfs求出具体拆分的组合。
Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | public static List<String> wordBreak(String s, Set<String> dict) { //create an array of ArrayList<String> List<String> dp[] = new ArrayList[s.length()+ 1 ]; dp[ 0 ] = new ArrayList<String>(); for ( int i= 0 ; i<s.length(); i++){ if ( dp[i] == null ) continue ; for (String word:dict){ int len = word.length(); int end = i+len; if (end > s.length()) continue ; if (s.substring(i,end).equals(word)){ if (dp[end] == null ){ dp[end] = new ArrayList<String>(); } dp[end].add(word); } } } List<String> result = new LinkedList<String>(); if (dp[s.length()] == null ) return result; ArrayList<String> temp = new ArrayList<String>(); dfs(dp, s.length(), result, temp); return result; } public static void dfs(List<String> dp[], int end,List<String> result, ArrayList<String> tmp){ if (end <= 0 ){ String path = tmp.get(tmp.size()- 1 ); for ( int i=tmp.size()- 2 ; i>= 0 ; i--){ path += " " + tmp.get(i) ; } result.add(path); return ; } for (String str : dp[end]){ tmp.add(str); dfs(dp, end-str.length(), result, tmp); tmp.remove(tmp.size()- 1 ); } } |
Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | public List<String> wordBreak(String s, Set<String> wordDict) { ArrayList<String> [] pos = new ArrayList[s.length()+ 1 ]; pos[ 0 ]= new ArrayList<String>(); for ( int i= 0 ; i<s.length(); i++){ if (pos[i]!= null ){ for ( int j=i+ 1 ; j<=s.length(); j++){ String sub = s.substring(i,j); if (wordDict.contains(sub)){ if (pos[j]== null ){ ArrayList<String> list = new ArrayList<String>(); list.add(sub); pos[j]=list; } else { pos[j].add(sub); } } } } } if (pos[s.length()]== null ){ return new ArrayList<String>(); } else { ArrayList<String> result = new ArrayList<String>(); dfs(pos, result, "" , s.length()); return result; } } public void dfs(ArrayList<String> [] pos, ArrayList<String> result, String curr, int i){ if (i== 0 ){ result.add(curr.trim()); return ; } for (String s: pos[i]){ String combined = s + " " + curr; dfs(pos, result, combined, i-s.length()); } } |
Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class Solution { Map<String, List<String>> done = new HashMap<>(); Set<String> dict; public List<String> wordBreak(String s, Set<String> dict) { this .dict = dict; done.put( "" , new ArrayList<>()); done.get( "" ).add( "" ); return dfs(s); } List<String> dfs(String s) { if (done.containsKey(s)) { return done.get(s); } List<String> ans = new ArrayList<>(); for ( int len = 1 ; len <= s.length(); len++) { String s1 = s.substring( 0 , len); String s2 = s.substring(len); if (dict.contains(s1)) { List<String> s2_res = dfs(s2); for (String item : s2_res) { if (item == "" ) { ans.add(s1); } else { ans.add(s1 + " " + item); } } } } done.put(s, ans); return ans; } } |
Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class Solution( object ): def wordBreak( self , s, wordDict): """ :type s: str :type wordDict: Set[str] :rtype: List[str] """ n = len (s) max_len = 0 for string in wordDict: max_len = max (max_len, len (string)) can_break = [ False for _ in xrange (n + 1 )] valid = [[ False ] * n for _ in xrange (n)] can_break[ 0 ] = True for i in xrange ( 1 , n + 1 ): for l in xrange ( 1 , min (i, max_len) + 1 ): if can_break[i - l] and s[i - l:i] in wordDict: valid[i - l][i - 1 ] = True can_break[i] = True result = [] if can_break[ - 1 ]: self .wordBreakHelper(s, valid, 0 , [], result) return result def wordBreakHelper( self , s, valid, start, path, result): if start = = len (s): result.append( " " .join(path)) return for i in xrange (start, len (s)): if valid[start][i]: path + = [s[start:i + 1 ]] self .wordBreakHelper(s, valid, i + 1 , path, result) path.pop() |
C++:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Solution { public : vector<string> wordBreak(string s, unordered_set<string>& wordDict) { vector<string> res; string out; vector< bool > possible(s.size() + 1, true ); wordBreakDFS(s, wordDict, 0, possible, out, res); return res; } void wordBreakDFS(string &s, unordered_set<string> &wordDict, int start, vector< bool > &possible, string &out, vector<string> &res) { if (start == s.size()) { res.push_back(out.substr(0, out.size() - 1)); return ; } for ( int i = start; i < s.size(); ++i) { string word = s.substr(start, i - start + 1); if (wordDict.find(word) != wordDict.end() && possible[i + 1]) { out.append(word).append( " " ); int oldSize = res.size(); wordBreakDFS(s, wordDict, i + 1, possible, out, res); if (res.size() == oldSize) possible[i + 1] = false ; out.resize(out.size() - word.size() - 1); } } } }; |
类似题目:
[LeetCode] 139. Word Break 单词拆分
All LeetCode Questions List 题目汇总
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架