139.单词拆分
给定一个非空字符串 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
解题思路:
深度优先搜索(DFS),动态规划(DP),字符串哈希。
1. 字符串wordDict进入哈希表。这里可以用unorderded_map来实现比较方便。期间还可以统计单词的最小长度min和最大长度max。
2. 从pos=0开始处搜索,查找长度为[min,max]的子串,max还要根据s的规模确定是否溢出。每得到一个单词在map中出现,就递归。
3. 为了防止已经搜索的路径重复搜索,应该建立bool dp[10001],储存已经访问过的路径。
class Solution { public: bool wordBreak(string s, vector<string>& wordDict) { int size = wordDict.size(), i; if (size == 0) return false; ss = s; for (i = 1; i <= size; i++) { mp[wordDict[i - 1]] = true; if (int(wordDict[i - 1].size()) > max) max = int(wordDict[i - 1].size()); if (int(wordDict[i - 1].size()) < min) min = int(wordDict[i - 1].size()); } length = s.size(); if (length == 0) return false; return DFS(0); } bool DFS(int pos) { if (pos == length) return true; int left = min, right = max; if (right + pos - 1 >= length) right = length - pos; string str; bool sgn; for (int i = left; i <= right; i++) { str = ss.substr(pos, i); if (mp[str] == true) { if (dp[pos + i] != 0) { sgn = (dp[pos + i] == -1 ? false : true); } else { sgn = DFS(pos + i); dp[pos + i] = (sgn == true ? 1 : -1); } if (sgn == true) return true; } else { mp.erase(str); } } return false; } private: int dp[10001]; unordered_map<string, bool> mp; int max = 0, min = INT32_MAX; int length; string ss; }; |
140.单词拆分II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
- 分隔时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
输入: s = "catsanddog
" wordDict =["cat", "cats", "and", "sand", "dog"]
输出:[ "cats and dog", "cat sand dog" ]
示例 2:
输入: s = "pineapplepenapple" wordDict = ["apple", "pen", "applepen", "pine", "pineapple"] 输出: [ "pine apple pen apple", "pineapple pen apple", "pine applepen apple" ] 解释: 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog" wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: []
解题思路:
和139一致,只不过要保存每一种搜索的结果。
class Solution { public: vector<string> wordBreak(string s, vector<string>& wordDict) { int size = wordDict.size(), i; if (size == 0) return{}; ss = s; for (i = 1; i <= size; i++) { mp[wordDict[i - 1]] = true; if (int(wordDict[i - 1].size()) > max) max = int(wordDict[i - 1].size()); if (int(wordDict[i - 1].size()) < min) min = int(wordDict[i - 1].size()); } length = s.size(); if (length == 0) return{}; vector<string> res = DFS(0); return res; } vector<string> DFS(int pos) { visit[pos] = true; if (pos >= length) { dp[pos].push_back(""); return{ "" }; } int left = min, right = max; if (right + pos - 1 >= length) right = length - pos; string str, sgn, str1; vector<string> vs; for (int i = left; i <= right; i++) { str = ss.substr(pos, i); if (mp[str] == true) { int size = dp[pos + i].size(); if (visit[pos+i] == true) { vs = dp[pos + i]; } else { vs = DFS(pos + i); } for (int j = 1; j <= int(vs.size()); j++) { if (vs[j - 1] == "") { dp[pos].push_back(str); } else dp[pos].push_back(str +" "+ vs[j - 1]); } } else mp.erase(str); } return dp[pos]; } private: vector<string> dp[10001]; bool visit[10001]; unordered_map<string, bool> mp; int max = 0, min = INT32_MAX; int length; string ss; }; |