面试题 17.13. 恢复空格
Title
哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。像句子"I reset the computer. It still didn’t boot!“已经变成了"iresetthecomputeritstilldidntboot”。在处理标点符号和大小写之前,你得先把它断成词语。当然了,你有一本厚厚的词典dictionary,不过,有些词没在词典里。假设文章用sentence表示,设计一个算法,把文章断开,要求未识别的字符最少,返回未识别的字符数。
示例:
输入:
dictionary = [“looked”,“just”,“like”,“her”,“brother”]
sentence = “jesslookedjustliketimherbrother”
输出: 7
解释: 断句后为"jess looked just like tim her brother",共7个未识别字符。
提示:
0 <= len(sentence) <= 1000
dictionary中总字符数不超过 150000。
你可以认为dictionary和sentence中只包含小写字母。
Trie + 动态规划
Solve
定义 dp[i] 表示考虑前 i 个字符最少的未识别的字符数量,从前往后计算 dp 值。
考虑转移方程,每次转移的时候我们考虑第 j(j≤i) 个到第 i 个字符组成的子串 sentence[j−1⋯i−1] (注意字符串下标从 0 开始)是否能在词典中找到,如果能找到的话按照定义转移方程即为
dp[i]=min(dp[i],dp[j−1])dp[i]=min(dp[i],dp[j−1])dp[i]=min(dp[i],dp[j−1])
否则没有找到的话我们可以复用 dp[i−1] 的状态再加上当前未被识别的第 i 个字符,因此此时 dp 值为
dp[i]=dp[i−1]+1dp[i]=dp[i−1]+1dp[i]=dp[i−1]+1
最后问题化简成了转移的时候如何快速判断当前子串是否存在于词典中,可以通过字典树 Trie 来优化查找。
Trie 是一种最大程度利用多个字符串前缀信息的数据结构,它可以在 O(w) 的时间复杂度内判断一个字符串是否是一个字符串集合中某个字符串的前缀,其中 w 代表字符串的长度。
我们将词典中所有的单词「反序」插入字典树中,然后每次转移的时候我们从当前的下标 i 出发倒序遍历 i−1,i−2,⋯,0。在 Trie 上从根节点出发开始走,直到走到当前的字符 sentence[j] 在 Trie 上没有相应的位置,说明 sentence[j⋯i−1] 不存在在词典中,且它已经不是「任意一个单词的后缀」,此时我们直接跳出循环即可。否则,我们需要判断当前的子串是否是一个单词,这里我们直接在插入 Trie 的时候在单词末尾的节点打上一个 isEnd 的标记即可,这样我们在走到某个节点的时候就可以判断是否是一个单词的末尾并根据状态转移方程更新我们的 dp 值。
具体实现以及示例的图画解析可以看下面:
Code
动态规划
def respace(self, dictionary: List[str], sentence: str) -> int:n = len(sentence)dp = [i for i in range(n + 1)]for i in range(n):for j in range(i, -1, -1):if sentence[j:i + 1] in dictionary:dp[i + 1] = min(dp[i + 1], dp[j])else:dp[i + 1] = min(dp[i + 1], dp[i] + 1)return dp[-1]
动态规划+字典树
class Solution:def respace(self, dictionary, sentence: str) -> int:trie = Trie()# 初始化字典树for word in dictionary:cur = triefor i in range(len(word)-1, -1, -1):cur = cur.next_nodes[word[i]]cur.isEnd = Truedp = [float('inf') for _ in range(len(sentence)+1)]dp[0] = 0for i in range(1, len(sentence)+1):dp[i] = dp[i - 1] + 1j = icur = triewhile j >= 1 and sentence[j-1] in cur.next_nodes:cur = cur.next_nodes[sentence[j]]if cur.isEnd == True:dp[i] = min(dp[i], dp[j-1])if dp[i] == 0:breakj -= 1return dp[-1]class Trie:def __init__(self):self.next_nodes = collections.defaultdict(Trie)self.isEnd = False
面试题 17.13. 恢复空格相关推荐
- 程序员面试金典 - 面试题 17.13. 恢复空格(DP+Trie树)
文章目录 1. 题目 2. 解题 2.1 动态规划 2.2 Trie树 1. 题目 哦,不!你不小心把一个长篇文章中的空格.标点都删掉了,并且大写也弄成了小写. 像句子"I reset th ...
- [Leetcode][程序员面试金典][面试题17.13][JAVA][恢复空格][动态规划][Trie][字符串哈希]
[问题描述][中等] [解答思路] 1. 动态规划 动态规划流程 第 1 步:设计状态 dp[i] 表示字符串的前 i 个字符的最少未匹配数. 第 2 步:状态转移方程 假设当前我们已经考虑完了前 i ...
- 计算机二级考试题库vb知识点,国家计算机二级考试题库 VB上机试题第13套
国家计算机二级考试题库 VB上机试题第13套: 1. 基本操作(2小题,每小题15分,共计30分) 注意:下面出现的"考生文件夹"均为%USER% 请根据以下各小题的要求设计Vis ...
- [LeetCode][C++]面试题 17.07. 婴儿名字/并查集
面试题 17.07. 婴儿名字 每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量.有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公 ...
- 面试题.17.07.婴儿名字--并查集
LeetCode 面试题 17.07.婴儿名字 每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量.有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被 ...
- 并查集之面试题 17.07. 婴儿名字
并查集之面试题 17.07. 婴儿名字 前言 一, 面试题 17.07. 婴儿名字 二,解题思路 1, a和b是朋友, b和c是朋友,那a和c也是朋友.这就是典型并查集类型 2, 字典序 3, 三, ...
- 面试题 17.07. 婴儿名字
面试题 17.07. 婴儿名字 每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量.有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公 ...
- 【每日一题】 面试题 17.14. 最小K个数
面试题 17.14. 最小K个数
- python【力扣LeetCode算法题库】面试题 17.16- 按摩师(DP)
面试题 17.16. 按摩师 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接.在每次预约服务之间要有休息时间,因此她不能接受相邻的预约.给定一个预约请求序列,替按摩师找到最优的预 ...
最新文章
- html5转apicloud,使用APICloud编写优雅的HTML5代码
- 几个受益终身的英文缩写
- Linux环境下如何编译和执行c程序
- CSS浮动(三)---Float
- TensorFlow基础笔记(5) VGGnet_test
- MySQL数据库的优化-运维架构师必会高薪技能,笔者近六年来一线城市工作实战经验...
- java常见面试题及答案(基础题122道,代码题19道),java高级面试笔试题
- 已解决:手动打包war包结果无法在Tomcat中部署
- TypeScript算法专题 - [双链表1] - 双链的概念及其实现
- 关于网上商城开发的随笔记录1
- CentOS7安装dnf报错:No package dnf available
- 求n从1到20阶乘的和(即1+2!+3!+4!+...+20!)
- 算法导论随笔(十四):NP完全性之P问题、NP问题、NPC问题和NP难问题
- 视频解析网站 服务器上,视频云解析服务器上
- python脚本实现GNSS数据自动下载
- Core Data详解
- 现要求输入一个整数n,请输出斐波那契数列的第n项
- Electric Fences_usaco3.4_皮克定理
- IPC$漏洞利用简介
- 3个5相乘列乘法算式_「百树云课堂」初一数学必考的知识点(21个)
热门文章
- pip安装python模块遇到一直出现retrying的问题
- C语言实现随机生成0~100的数
- Linux系统网络基础知识及配置
- JS移动客户端--触屏滑动事件 banner图效果
- PB中获得dropdownlistbox下拉选框中选择项的序列号
- Linux 下安装 Oracle9i
- Kruscal算法+并查集 求解最小生成树
- 生成1~n的全排列,按字典序输出
- (11.06)Java小知识
- myEclipse开发内存溢出解决办法myEclipse调整jvm内存大小java.lang.OutOfMemoryError: PermGen space及其解决方法...