专栏首页BFE.dev前端刷题日记BFE.dev前端刷题#55. HTML字符串中高亮关键字
原创

BFE.dev前端刷题#55. HTML字符串中高亮关键字

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'
复制代码

我的想法是:

  1. 当我们发现关键字时,比如上述例子中的'Front',我们可以记录下首尾的index,startend
  2. 然后便历从startend开始的字符串,如果又发现关键词的时候,根据需要更新end,比如我们有可能遇到 ontE,从而end被延后。
  3. 遇到end的时候停止,此时 startend之间的字符都需要高亮。

上述逻辑处理了重复的情况,那相邻的情况呢?比如这样:

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 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • BFE.dev前端刷题 104. 按层遍历DOM树

    可以看到我们只需要不停的从左边取出元素,然后将其子元素从右边不停放入即可。这用queue实现。

    JSer
  • BFE.dev前端刷题 33. 实现Promise.allSettled()

    和Promise.all()不同,Promise.allSettled()即使是遇到rejection也会等待所有的promise到最后。所以我们只需要用一个a...

    JSer
  • BFE.dev前端刷题#58. 获取DOM tree高度

    一个tree的高度 = 子tree的最大高度 + 1。由此我们可以很容易地得到递归解法。

    JSer
  • 谨慎使用 Laravel 的 Model 复制(replicate)功能

    今天分享一个刚挖的坑,我们的产品有一个交互是用户可以复制自己的日程,我们当时实现的时候仅仅花了不到半小时就上线了,完事还夸了 Eloquent 真的是面面俱到,...

    overtrue
  • 财报公布,它们依然是我们心中的阿里和腾讯

    孟永辉
  • 如何打造自己的PoC框架-Pocsuite3-框架篇

    本节笔者将按照Pocsuite框架结构以及工程化实践,来实现一款自己的PoC框架。为了开一个好头,我们先取一个好听的名字,想威武霸气一些可以取上古神器之类的,诸...

    Seebug漏洞平台
  • Mac 下安装node.js

    Node.js 是一个用Chrome's V8 JavaScript engine 构建的 JavaScript 运行时框架。Node.js 使用事件驱动、非阻...

    Haley_Wong
  • VMware Workstation 内部错误解决方案

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。

    拓荒者
  • promise的使用方法

    异步操作作为JavaScript中的一大特色,解决了JavaScript单线程运行的一个难题,但是很多时候有问题也在于这上面。最大的问题之一,就是异步操作过多的...

    OECOM
  • 验证码的故事 (2)

    上次我们说到了路易斯·冯·安(Luis von Ahn)发明的,既能拦截网络垃圾 spam、又能顺便帮助进行古籍的数字化工作的验证码工具--reCAPTCHA。...

    Crossin先生

扫码关注云+社区

领取腾讯云代金券