题目140:单词拆分II
说明:
分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例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"]
输出:
[]
分析
可以动态规划也可以回溯方法,这里还是使用回溯方法,但如果普通的回溯方法会超时,这里需要做一些优化。
将输入的wordDict的存储的容易由vector变成set,优化查询速度
将wordDict中每个字符串的长度存储到set中,回溯过程中字符串只截取set中有的长度,避免不必要的字符串截取
将每次回溯计算的结果存储下来,避免不必要的递归操作
代码
class Solution {public:vector<string> wordBreak(string s, vector<string>& wordDict) {GeneSets(wordDict); // vector convert to setreturn BackTrace(s, 0);}vector<string> BackTrace(string &s, int idx) {if (maps.find(idx) != maps.end()) { // 避免不必要的递归return maps[idx];}int s_size = s.size();vector<string> ret;if (idx == s_size) {ret.emplace_back("");return ret;}for (int i = min_len; i <= max_len; ++i) {if (idx + i > s_size) { break; }// 避免不必要的字符串截取if (len_sets.find(i) == len_sets.end()) { continue; }string tem = s.substr(idx, i);if (str_sets.find(tem) != str_sets.end()) {vector<string> tem_ret = BackTrace(s, idx + i);maps[idx+i] = tem_ret; // 保存每次计算的结果for (auto &tem_str : tem_ret) {string ss = (tem_str == "") ? "" : (" " + tem_str);ret.emplace_back(tem + ss);}}}return ret;}map<int, vector<string>> maps;set<string> str_sets;set<int> len_sets;int min_len = INT_MAX;int max_len = 0;void GeneSets(vector<string>& wordDict) {for (auto &s : wordDict) {int size = s.size();min_len = min(min_len, size);max_len = max(max_len, size);str_sets.emplace(s);len_sets.emplace(size);}}};

