LeetCode Week13: Word Break系列
来源:互联网 发布:手机cf国外视频软件 编辑:程序博客网 时间:2024/06/05 08:39
这周完成的还是Dynamic Programming 部分的题目,这里选择word break系列的两道题目进行分析。
一、Word Break
题目
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words.
For example, given
s = “leetcode”,
dict = [“leet”, “code”].
Return true because “leetcode” can be segmented as “leet code”.
我的分析
这道题可以使用动态规划来求解,简单来说,假设dp[i]表示前i个元素组成的序列是否可以正确划分,那么对于一个序列abcdab,长度为6,那么当我们判断abcda都是合法可分符合字典内容时,对于第6个元素:
- 从第0到第5个元素,从右到左进行一个遍历,即最开始遍历ab是否存在于字典中且a以前的序列是否合法可分,如果满足条件,那么就说明abcdab是合法可分的,如果a不能满足这个条件,那么继续判断dab是否存在于字典中,且前面的序列abc是否可分,依次进行下去;
- 这里有一个巧妙的点:我们判断ab是否存在的时候,其实前面的序列abcd已经遍历过ab了,那么ab一定会存在于字典中
- 整个过程的状态转移方程可以写作 dp[i] = I(s[j, i]) & dp[j], j = 0, 1, 2, ……, n。其中I(
⋅ )表示如果s[j,i] 存在于字典中,则返回1,否则返回0;
代码
结合分析的结果可得如下代码:
class Solution {public: bool wordBreak(string s, vector<string>& wordDict) { int len = s.size(); vector<bool> dp(len+1,false); dp[0] = true; for(int i = 1; i <= len; i++) //从前一个元素开始,判断新加入的元素是否存在 for(int j = i-1; j >= 0; j--){ // 判断新加入的元素是否存在 string str = s.substr(j,i-j); // 新加入的元素和之前的序列都存在时,说明整个序列都存在 if(dp[j] && find(wordDict.begin(),wordDict.end(),str) != wordDict.end()){ dp[i] = true; break; } } return dp[len]; }};
二、Word Break 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. You may assume the dictionary does not contain duplicate words.
Return all such possible sentences.
For example, given
s = “catsanddog”,
dict = [“cat”, “cats”, “and”, “sand”, “dog”].
A solution is [“cats and dog”, “cat sand dog”].
我的分析
这道题是上一道题的引申,可以在上一道题的基础上,结合DFS来求解。
- 首先,需要判断序列是否可分,在判断序列是否可分中,使用dp[i][j]来表示,以元素i结尾的序列中,可以在j位置划分的合法性,如果在j位置可以划分,那么dp[i][j]为true。例如对于catsand,有两种划分(cat/sand以及cats/and),那么第7行(d是第7个元素),第3列和第4列的值都是true,其他列元素都是false;
- 在得到不同长度的序列的合法性及划分位置后,可以根据这些信息划分数据加入空格:从序列的原始长度出发,先从后往前得到第一个可划分的单词,之后根据剪掉这个单词之后的剩余序列的划分位置继续做划分,简单来说,在找到一个合法单词后,会把划分这个单词之后的剩余划分情况遍历完毕,之后再往前遍历,这就是一个DFS的过程。
代码
结合上述分析可以得到如下代码:
class Solution {public: vector<string> wordBreak(string s, vector<string>& wordDict) { vector<string> res; if(s.length() == 0 || wordDict.empty()) return res; // 判断以前i个元素中可以在那些位置划分得到符合条件的一个或多个单词 vector<vector<bool> >dp(s.length()+1, vector<bool>(s.length())); dp_wordBreak_judge(s, wordDict, dp); // 得到合法的序列的组合形式 vector<string> tmp; dp_wordBreak(s, wordDict, res, tmp, dp, s.length()); return res; } void dp_wordBreak_judge(string s, vector<string> &wordDict, vector<vector<bool> >&dp){ vector<bool>tmp(s.size()+1,false); tmp[0] = true; for(int i = 1; i <= s.size(); i++){ //从前一个元素开始,判断新加入的元素是否存在 for(int j = i-1; j >= 0; j--){ // 判断新加入的元素是否存在 string str = s.substr(j,i-j); // 新加入的元素和之前的序列都存在时,说明整个序列都存在 if(tmp[j] && find(wordDict.begin(),wordDict.end(),str) != wordDict.end()){ tmp[i] = true; dp[i][j] = true; } } } } void dp_wordBreak(string s, vector<string> &wordDict, vector<string>&res,vector<string> tmp, vector<vector<bool> >&dp, int cur){ int len = s.length(); if(cur == 0){ string str=tmp[tmp.size()-1]; for(int idx = tmp.size()-2; idx >=0; idx--) str += " "+tmp[idx]; res.push_back(str); return ; } for(int i = 0; i < len; i++){ // 倒序遍历第一个单词 if(dp[cur][i] == true){ // 得到最后一个单词,继续析取前面的序列 tmp.push_back(s.substr(i,cur-i)); dp_wordBreak(s, wordDict, res, tmp, dp,i); tmp.pop_back(); } } }};
- LeetCode Week13: Word Break系列
- leetcode:string hard系列三:word break
- leetcode Word Break & Word Break ||
- LeetCode Week13
- LeetCode Week13
- leetcode week13
- Leetcode: Word Break
- [leetcode]Word Break
- [leetcode]Word Break II
- LeetCode:Word Break
- LeetCode:Word Break II
- Leetcode: Word Break II
- [LeetCode] Word Break
- [LeetCode] Word Break II
- LeetCode: Word Break
- leetcode之Word Break
- [LeetCode]Word Break II
- [LeetCode]Word Break
- 高性能mysql笔记(三)mysqlslap性能测试
- 腾讯高性能RPC开发框架Tars实现服务治理(微服务)
- Maven传递依赖冲突解决
- 最小点覆盖问题 二分图
- 2016背包专题1008
- LeetCode Week13: Word Break系列
- CSS设计的美丽之佛背景、相对定位、绝对定位、box居中(小作品)
- Unity使用lzma的测试记录
- highcharts问题汇总
- 静态代码扫描(六)——火线针对资源关闭问题的横向对比报告
- F
- HDOJ 2024 C语言合法标识符
- Jekyll背景post设置参考
- 51单片机有关变量及初始化问题