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 复制代码
这是一个有趣的问题。
感谢阅读。希望能有所帮助,
如果有兴趣可以在 这里自己尝试一下。
原创声明,本文系作者授权云+社区发表,未经许可,不得转载。
如有侵权,请联系 yunjia_community@tencent.com 删除。
我来说两句