哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。
像句子"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个未识别字符
思路:
首先要把字符串所有可能存在的切分规则枚举出来
对 sentence 进行双层遍历
另外,每次单词被分割出来之后,需要判断这个单词是否在 wordDict 中
逻辑:
直到添加到字母首位。
注意:
每次 i 增加时,其其实值应该为 dp[i-1] + x
/**
* @param {string[]} dictionary
* @param {string} sentence
* @return {number}
*/
var respace = function (dictionary, sentence) {
let len = sentence.length,
dp = new Array(len + 1).fill(0)
for (let i = 1; i <= len; i++) {
dp[i] = dp[i - 1] + (dictionary.includes(sentence[i - 1]) ? 0 : 1)
for (let j = i - 1; j >= 0; j--) {
let word = sentence.substring(j, i)
if (dictionary.includes(word)) {
dp[i] = Math.min(dp[i], dp[j])
} else {
dp[i] = Math.min(dp[i], dp[j] + i - j)
}
}
}
return dp[len]
}
上面判断分割的字符是否包含在 dictionary 中用了 includes
includes 内部还有一次轮询,可以使用哈希来替代,优化时间
哈希方法可以用 set,map,object 实现
/**
* @param {string[]} dictionary
* @param {string} sentence
* @return {number}
*/
var respace = function (dictionary, sentence) {
let len = sentence.length,
dp = new Array(len + 1).fill(0),
map = new Map()
// 字典生成哈希
dictionary.forEach((i) => map.set(i))
for (let i = 1; i <= len; i++) {
dp[i] = dp[i - 1] + (map.has(sentence[i - 1]) ? 0 : 1)
for (let j = i - 1; j >= 0; j--) {
if (map.has(sentence.substring(j, i))) {
dp[i] = Math.min(dp[i], dp[j])
} else {
dp[i] = Math.min(dp[i], dp[j] + i - j)
}
}
}
return dp[len]
}
/**
* @param {string[]} dictionary
* @param {string} sentence
* @return {number}
*/
var respace = function (dictionary, sentence) {
let len = sentence.length,
dp = new Array(len + 1).fill(0)
for (let i = 1; i <= len; i++) {
// 初始值
dp[i] = dp[i - 1] + (dictionary.includes(sentence[i - 1]) ? 0 : 1)
// 遍历字典,分割字符
for (let j = 0; j < dictionary.length; j++) {
let item = dictionary[j],
itemLen = item.length,
strStart = i - ditemLen
// 小于字段字符长度不分割
if (i < itemLen) continue
if (sentence.substring(strStart, i) === item) {
// 存在则取该位置不匹配的最小值
dp[i] = Math.min(dp[strStart], dp[i])
}
}
}
return dp[len]
}
优化:
则优化后为:
/**
* @param {string[]} dictionary
* @param {string} sentence
* @return {number}
*/
var respace = function (dictionary, sentence) {
let dp = [0],
len = sentence.length
for (let i = 1; i <= len; i++) {
dp[i] = dp[i - 1] + (dictionary.includes(sentence[i - 1]) ? 0 : 1)
for (let j = 0; j < dictionary.length; j++) {
let item = dictionary[j]
if (sentence.substring(i - item.length, i) === item) {
dp[i] = Math.min(dp[i], dp[i - item.length])
}
}
}
return dp[dp.length - 1]
}
博客: 小书童博客
公号: 坑人的小书童