BFE.dev 有点像前端的 leetCode,以下是我的刷题记录。
本文所涉的是 BFE.dev#55. HTML 字符串中高亮关键字
剖析
题目的指标是用 <em>
高亮关键字,如下:
highlightKeywords(
'Hello FrontEnd Lovers',
['Hello', 'Front', 'JavaScript']
)
// '<em>Hello</em> <em>Front</em>End Lovers'
看起来很简略,只须要找到关键字替换即可。不过遇到反复的状况就有点麻烦了,比方下:
highlightKeywords(
'Hello FrontEnd Lovers',
['Front', 'FrontEnd', 'JavaScript']
)
// 'Hello <em>FrontEnd</em> Lovers'
我的想法是:
- 当咱们发现关键字时,比方上述例子中的
'Front'
,咱们能够记录下首尾的 index,start
和end
。 - 而后便历从
start
到end
开始的字符串,如果又发现关键词的时候,依据须要更新end
,比方咱们有可能遇到ontE
,从而end
被延后。 - 遇到
end
的时候进行,此时start
和end
之间的字符都须要高亮。
上述逻辑解决了反复的状况,那相邻的状况呢?比方这样:
highlightKeywords(
'Hello FrontEnd Lovers',
['Front', 'End', 'JavaScript']
)
// 'Hello <em>FrontEnd</em> Lovers'
对于这种状况,咱们能够一直反复上述过程,而后找到可能的相邻的关键词即可。
代码
首先咱们解决如下一个子问题:
给定一个 start index,返回其最长高亮关键词的 end index。
没有的话返回 -1
根据上述剖析,该问题能够比拟容易的解决,如下:
const keywordSet = new Set(keywords)
const getEndForEm = (start) => {
let isEmFound = false
let end = start
// 如果找到新的关键词,就不断更新 end
// 遇到 end 的时候进行
while (start <= end) {for (let word of keywordSet) {
const length = word.length
if (html.slice(start, start + length) === word) {
isEmFound = true
end = Math.max(end, start + length - 1)
}
}
start += 1
}
return isEmFound ? end : -1
}
OK,当初有了上述函数,问题变得比较简单。咱们只须要对于每一个 index,循环调用上述函数失去最终间断区间即可。
let result = ''
for (let i = 0; i < html.length;) {let endForEm = getEndForEm(i)
// 查看是否有相邻关键词
while (endForEm > -1) {const nextEndForEm = getEndForEm(endForEm + 1)
if (nextEndForEm === -1) {break}
endForEm = nextEndForEm
}
if (endForEm > -1) {result += '<em>' + html.slice(i, endForEm + 1) + '</em>'
i = endForEm + 1
} else {result += html[i]
i += 1
}
}
return result
通过撒花!
这是一个乏味的问题。
感激浏览。心愿能有所帮忙,
如果有趣味能够在 这里本人尝试一下。