为了账号安全,请及时绑定邮箱和手机立即绑定

RegEx 性能:交替 vs Trie

RegEx 性能:交替 vs Trie

鸿蒙传说 2021-06-02 09:20:01
对于Wolfram 语言的 Google Prettify 语法高亮器,我需要将所有标识符与大约 7000 个内置函数名称的大列表进行匹配,以将它们高亮显示为关键字。过去,我只是使用了一个由许多交替组成的正则表达式。举一个具体的例子,这里是所有以 开头的函数Plot:(:?Plot|Plot3D|Plot3Matrix|PlotDivision|PlotJoined|PlotLabel|PlotLabels|PlotLayout|PlotLegends|PlotMarkers|PlotPoints|PlotRange|PlotRangeClipping|PlotRangeClipPlanesStyle|PlotRangePadding|PlotRegion|PlotStyle|PlotTheme)从理论上讲,这是一个糟糕的选择,因为每个替代关键字都需要重复进行子匹配。人们可以做的是构建一个Trie(或前缀树)并从中构建一个正则表达式。如果前缀不正确,这将跳过所有子匹配。对于上面的单词,这看起来像这样(:?Plot(?:3(?:D|Matrix)|Division|Joined|L(?:a(?:bel(?:s)?|yout)|egends)|Markers|Points|R(?:ange(?:Clip(?:PlanesStyle|ping)|Padding)?|egion)|Style|Theme)?)虽然这看起来有点乱,但想法很简单:它测试前缀Plot,如果不匹配,则不需要进一步测试。如果匹配,则跳转到内部表达式并测试下一个前缀,直到它具有完全匹配或不匹配。我已经为所有 7000 个与自身匹配的关键字和 7000 个字典单词的正则表达式计时,作为使用 Kotlin 的反例。Trie 实现需要 78 毫秒,而交替正则表达式需要 523 毫秒。这是我预期的巨大改进。但是,在 JavaScript 中,Trie 实现似乎有点慢。出于分析的目的,我设置了 2 个网页,它们使用两种不同的方法调用美化引擎。这是 Trie 实现,这是交替实现。然后我使用 Chrome 开发工具对此进行了分析,但我对 JS 并不是特别有经验。问题:有人可以解释一下,为什么当 (a) 正则表达式本身更小(尽管嵌套严重)和 (b) 正则表达式在匹配时理论上应该有很多捷径时,为什么 Trie 正则表达式看起来更慢?鉴于这里和这里的两个测试站点甚至纯正则表达式,有人能告诉我如何正确地描述它吗?关键字和字典词列表可在此处获得。
查看完整描述

1 回答

  • 1 回答
  • 0 关注
  • 295 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信