虫虫首页|资源下载|资源专辑|精品软件
登录|注册

您现在的位置是:首页 > 技术阅读 >  每日一题:单词拆分问题

每日一题:单词拆分问题

时间:2024-02-14

题目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"]
输出:
[]

分析

可以动态规划也可以回溯方法,这里还是使用回溯方法,但如果普通的回溯方法会超时,这里需要做一些优化。

  • 将输入的wordDict的存储的容易由vector变成set,优化查询速度

  • 将wordDict中每个字符串的长度存储到set中,回溯过程中字符串只截取set中有的长度,避免不必要的字符串截取

  • 将每次回溯计算的结果存储下来,避免不必要的递归操作

代码

class Solution {public:    vector<string> wordBreak(string s, vector<string>& wordDict) {        GeneSets(wordDict); // vector convert to set        return 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); } }};


C++线程池的实现之格式修订版

每日一题:正则表达式匹配


点此留言