单词拆分

力扣题目链接(opens new window)

给定一个非空字符串 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

思路

如果要往背包问题上靠的话,可以把wordDict中的单词视为"物品"把字符串s的长度视为背包容量(注意,这里说的是长度,即s.size)

思路听上去很常规,但是具体到实现方式上就有点复杂

五步走

1、确定dp数组含义

如果拿不准dp数组中的元素是什么类型,可以看看题目的示例返回的是什么类型的值,那一般就是需要找的值

这里题目要判定字典wordDict中的单词能不能拼成字符串s

那么实现过程中肯定要用字典wordDict中的单词与当前遍历区间内截取到的子串进行比较,要么相同要么不同,再结合示例的返回值,可以判断dp数组中的值应该是布尔类型

回到正题,dp数组究竟代表什么意思

假设有一个长度为i的字符串s的子串,若dp[i] = true

那么dp[i]表示该字符串可以拆分为1个或多个字典wordDict中的单词(可以理解为:dp[i]是对遍历过程中某个子串是否能拆分为wordDict中单词的一个认证,true就是能拆,false就是拆不了)

2+3、确定递推公式和初始化dp数组

这个递推公式的条件可太多了,为什么连起来一块说,看到后面就知道了

首先,因为我们要不断遍历字符串s并截取子串,通过查找子串是否存在于字典wordDict中来判断当前子串是否可以拆分

为什么要判断子串是否可以拆分?

因为一旦遍历完字符串s,那么此时的子串就是s本身了。进而就可以求s能不能被拆分为字典wordDict中的单词,这里体现了dp的思想,即前一轮遍历的子串会影响下一轮的,最终影响整个结果

所以,第一个条件是:所遍历区间内的子串必须出现在字典中

在说第二个条件之前,有必要说一下 "不断遍历字符串s并截取子串" 的实现方式

其实就是双指针

		for (int i = 1; i <= s.size(); i++) {   // 遍历背包
for (int j = 0; j < i; j++) { // 遍历物品
string word = s.substr(j, i - j); //substr(起始位置,截取的个数)
if (wordSet.find(word) != wordSet.end() && dp[j]) {//这里wordSet是一个unordered_set
dp[i] = true;
}
}
}

下面用图来解释一下遍历过程

上图推导了两层for循环的遍历过程,其中,外层for循环负责遍历字符串s(也就是所谓的背包),而内层for则用来在[j,i]区间内遍历所有该区域内的子串,用来在wordSet中查询

如图所示,当外层for遍历到 i = 4 ,才获取到第一个能在wordSet中查询到的子串"leet"

为什么不是在i = 3时得到? 因为substr函数截取子串的区间时左闭右开的,详见 题外话

注意j遍历截取区间[j,i]内所有子串的顺序:它是先截最长的(如图所示)

此时,如果我们将dp[0]初始化为true

那么,每次i移动的时候,j重置为0,dp[j]就为true

若本次i移动到的位置,在j第一次获取子串时就能获取到目标子串的话,其实就找到了一个满足条件的子串

所以,此时的dp[i]也应该为true

因此,第二个条件就是:[j, i] 这个区间的子串是否出现在字典里

综上所述,本题的递推公式是: if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。(j < i )

初始化就是dp[0] = true(我认为完全是为了代码实现考虑,没有别的含义),其余位置是false

4、确定遍历顺序

因为题目说了,字符串s中可能会有"一个或多个"能够拆分为字典中单词的子串,也就是说背包中可以放多个相同的物品(单词),所以这是一个完全背包问题

而构成子串必须按一定顺序才能构成字符串s,所以本题的完全背包求的是排序(排列有序组合无序)(排列组合的区别详见

所以遍历顺序是:先背包容量后物品

代码

太绕了,终于到代码了

class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
//定义dp数组
vector<bool> dp(s.size() + 1, false);
//初始化
dp[0] = true; //遍历dp数组
//先将wordDict放入一个unordered_set便于使用子串进行查找
unordered_set<string> wordSet(wordDict.begin(), wordDict.end()); for(int i = 1; i <= s.size(); ++i){//先遍历背包,字符串s
for(int j = 0; j < i; ++j){//再遍历物品
string word = s.substr(j, i - j);//使用j不断截取区间内的子串
if(wordSet.find(word) != wordSet.end() && dp[j]) dp[i] = true;
}
}
return dp[s.size()];
}
};

【LeetCode动态规划#10】完全背包问题实战,其三(单词拆分,涉及集合处理字符串)的更多相关文章

  1. leetcode动态规划题目总结

    Hello everyone, I am a Chinese noob programmer. I have practiced questions on leetcode.com for 2 yea ...

  2. [LeetCode] 动态规划入门题目

    最近接触了动态规划这个厉害的方法,还在慢慢地试着去了解这种思想,因此就在LeetCode上面找了几道比较简单的题目练了练手. 首先,动态规划是什么呢?很多人认为把它称作一种"算法" ...

  3. Leetcode(10)正则表达式匹配

    Leetcode(10)正则表达式匹配 [题目表述]: 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或 ...

  4. 【1】【leetcode-139】【回溯超时、动态规划】单词拆分

    给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可以重复使用字典中的单词.你可以假设字典中没有重复的 ...

  5. [LeetCode] 139. Word Break 单词拆分

    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...

  6. 快速上手leetcode动态规划题

    快速上手leetcode动态规划题 我现在是初学的状态,在此来记录我的刷题过程,便于以后复习巩固. 我leetcode从动态规划开始刷,语言用的java. 一.了解动态规划 我上网查了一下动态规划,了 ...

  7. 【动态规划】简单背包问题II

    问题 B: [动态规划]简单背包问题II 时间限制: 1 Sec  内存限制: 64 MB提交: 21  解决: 14[提交][状态][讨论版] 题目描述 张琪曼:“为什么背包一定要完全装满呢?尽可能 ...

  8. [LeetCode] 140. Word Break II 单词拆分II

    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add space ...

  9. [LeetCode] 244. Shortest Word Distance II 最短单词距离 II

    This is a follow up of Shortest Word Distance. The only difference is now you are given the list of ...

  10. [LeetCode] 245. Shortest Word Distance III 最短单词距离 III

    This is a follow up of Shortest Word Distance. The only difference is now word1 could be the same as ...

随机推荐

  1. django_模板层的过滤器和继承

    **************************************************************************************************** ...

  2. JSP第五周作业

    1.教材p39实验3(听英语) <%@ page language="java" import="java.util.*" pageEncoding=&q ...

  3. sourcetree 合并某部分代码到另一个分支

    1. 在sourceTree中找到需要修改的分支 2.  在显示提交信息中,选择所有分支,这样就会出现soy分支的修改信息 3.  找到需要合并的某次commit, 点击,右键出现弹框 4. 选择 & ...

  4. VisualVM无法运行,修改配置文件

      在VisualVM安装位置下找到etc目录修改etc目录下的visualvm.conf文件 加入配置 参数 指定JDK或JRE路径,如 visualvm_jdkhome="C:\xxx\ ...

  5. DRF的视图与路由集Routers

    一 视图 Django REST framwork 提供的视图的主要作用: 控制序列化器的执行(检验.保存.转换数据) 控制数据库模型的操作 一 普通视图APIView 一 两个视图基类 1 APIV ...

  6. 痞子衡嵌入式:我为2021 TencentOS Tiny AIoT应用创新大赛做了场直播培训

    TencentOS Tiny AIoT 应用创新大赛是腾讯 TencentOS 团队联合恩智浦半导体.安谋科技(Arm China)发起的线上开发者活动,主要面向中小企业嵌入式工程师.广大嵌入式开发者 ...

  7. C_C++常用函数汇总

    1 string.h.cstring(C) (1)字符串连接函数 strcat.strncat strcat(char[ ], const char[ ]) strncat(char[ ], cons ...

  8. 小霸王、红白机、FC游戏、街机游戏在线玩的网站

    前段时间小笨就想做一个红白机在线玩的网站,作为90后,也玩过不少小霸王fc游戏,于是花了两个星期时间做了出来.前端界面略丑,因为小笨不是专做前端的,就将就一下吧,哈哈!网站暂时添加了数款怀旧游戏,包括 ...

  9. 【转载】谈谈GIS三维渲染引擎

    > 原文地址:https://zhuanlan.zhihu.com/p/419667971 三维引擎 minemap: 是我们公司的产品,主要以earth的形态展示,支持矢量切片+倾斜数据(这一 ...

  10. 地铁系统PC端代码

    代码顺序为项目文件顺序从上到下 package org.example.dao; import org.example.pojo.Station; import java.sql.ResultSet; ...