为什么正则表达式(a +)*在与aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa匹配时需要这么长时间?

时间:2014-09-17 10:19:13

标签: regex optimization

我正在阅读掌握正则表达式第3版的书,我对6.2.4.1“指数匹配”感到困惑

这本书上的例子有点复杂,为了更集中,我举了一个例子,与书上的那个基本相同

为什么匹配需要这么长时间,任何人都可以逐步解释匹配是如何执行的?提前致谢

正则表达式:

(a+)*

目标文字:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab

1 个答案:

答案 0 :(得分:1)

我不知道为什么'(a +)*'在那个目标上会很慢。 它应该快速匹配子字符串“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa。”

'(a +)* $'然而,在许多常见的正则表达式实现中会出现“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”的问题。

原因是灾难性的回溯。

会发生什么;

regexp匹配引擎在regexp开始时启动,查找重复一次或多次的令牌“a”。它找到一个'a',因此它是一个贪婪的匹配,它匹配所有'a'到'a +'。然后命中'b'。它现在有字符串“b”的剩余部分,它有一个选择;它可以尝试为(a +)*进行更多匹配 - 这会失败,或者它可以匹配字符串的结尾,这也会失败。由于两个选项都失败了,它需要回溯,匹配除了最后一个之外的所有选项。它现在具有字符串“ab”的剩余部分并且与之前的选择相同,但现在它可以为(a +)*进行另一个匹配。它这样做并且具有字符串“b”的剩余部分;把它留在我们之前看到的位置。所以它回溯,以便字符串的其余部分是“aab”。事情开始变得有趣;在它放弃和回溯之前,它需要尝试(a)(a)和(aa)。当它回溯时,它具有剩余的“aaab”,导致它在它放弃之前尝试(aaa),(aa)(a),(a)(aa)和(a)(a)(a)回溯了一步。

引擎可以切割长序列的方式在字符串长度中呈指数级增长,这就是导致正则表达式变慢的原因。