正则表达式替换的复杂性

时间:2008-08-22 03:02:35

标签: regex complexity-theory

我在任何地方都没有得到答案。正则表达式匹配和替换的运行时复杂性是什么?

编辑:我在python中工作。但是我想知道大多数流行的语言/工具(java,perl,sed)。

8 个答案:

答案 0 :(得分:13)

纯粹的理论立场:

我熟悉的实现是构建一个确定性有限自动机来识别正则表达式。这是在O(2 ^ m)中完成的,m是正则表达式的大小,使用标准算法。构建之后,通过它运行字符串在字符串的长度上是线性的 - O(n),n是字符串长度。在字符串中找到的匹配项的替换应该是恒定时间。

总的来说,我想O(2 ^ m + n)。

答案 1 :(得分:7)

可能感兴趣的其他理论信息。

为清楚起见,假设正则表达式的标准定义

http://en.wikipedia.org/wiki/Regular_language

来自形式语言理论。实际上,这意味着唯一的建筑物 材料是字母符号,连接和交替的操作符 Kleene闭合,以及单位和零常数(出现于 群理论原因)。一般来说,不要超载这个术语是一个好主意 尽管脚本语言的日常实践导致了这种情况 模糊度。

有一个NFA结构可以解决常规的匹配问题 表达式r和输入文本t在O(| r | | t |)时间和O(| r |)空间中,其中 | - |是长度函数。 Myers

进一步改进了该算法

http://doi.acm.org/10.1145/128749.128755

通过使用自动机节点列表和四俄罗斯范例来计算时间和空间复杂度O(| r | | t | / log | t |)。这个范例似乎是以四个俄罗斯人的名字命名的,他们写了一篇开创性的论文而不是 线上。然而,这些范例在这些计算生物学中得到了说明 讲义

http://lyle.smu.edu/~saad/courses/cse8354/lectures/lecture5.pdf

我觉得用数字和数字来命名范式是很有趣的 作者的国籍而不是他们的姓氏。

添加了反向引用的正则表达式的匹配问题是 NP-complete,由Aho证实

http://portal.acm.org/citation.cfm?id=114877

通过减少顶点覆盖问题,这是一个经典的NP完全问题。

要确定性地将正则表达式与反向引用匹配,我们可以 采用回溯(与Perl正则表达式引擎不同)来跟踪 输入文本t的可能子字,可以分配给变量 河只有O(| t | ^ 2)个子词可以分配给任何一个变量 在r。如果r中有n个变量,则可能有O(| t | ^ 2n) 分配。一旦将变量的子串分配固定,就可以了 问题简化为普通正则表达式匹配。因此 将正则表达式与反向引用匹配的最坏情况复杂度是 O(| T | ^ 2n)后

但是请注意,具有反向引用的正则表达式尚未出现 功能齐全的regexen。

例如,除了任何其他符号之外,请使用“不关心”符号 运营商。有几种多项式算法决定是否有一组 模式匹配输入文本。例如,Kucherov和Rusinowitch

http://dx.doi.org/10.1007/3-540-60044-2_46

将模式定义为单词w_1 @ w_2 @ ... @ w_n其中每个w_i是一个单词(不是正则表达式),“@”是一个不包含在任何一个中的可变长度“不关心”符号w_i。它们导出O((| t | + | P |)log | P |)算法,用于将一组模式P与输入文本t匹配,其中| t |是文本的长度,| P |是P中所有单词的长度。

了解这些复杂性措施如何结合以及如何结合将会很有趣 是具有正则表达式的匹配问题的复杂性度量 反向引用,“不关心”和其他有趣的实用功能 正则表达式。

唉,我还没有说过关于Python的话......:)

答案 2 :(得分:5)

取决于您使用正则表达式定义的内容。如果您允许连接,替代和Kleene-star的运算符,则时间实际上可以是O(m*n+m),其中m是正则表达式的大小,n是字符串的长度。您可以通过构建NFA(在m中为线性),然后通过维护您所处的状态集来模拟它,并为每个输入字母更新(在O(m)中)。

使正则表达式解析变得困难的事情:

  • 括号和反向引用:使用上述算法捕获仍然可以,尽管它会使复杂性更高,因此它可能是不可行的。反向引用提高了正则表达式的识别能力,其难度很大
  • 正向前瞻:只是交集的另一个名称,它将上述算法的复杂性提高到O(m^2+n)
  • 否定前瞻:构建自动机的灾难(O(2^m),可能是PSPACE-complete)。但是仍然可以用O(n^2*m)
  • 之类的动态算法来解决

请注意,通过具体实施,事情可能变得更好或更糟。根据经验,简单的特征应该足够快,并且明确(例如,不像a*a*)正则表达式更好。

答案 3 :(得分:2)

为了深入研究企业的答案,对于自动机的构造,O(2 ^ m)是最坏的情况,虽然它实际上取决于正则表达式的形式(对于一个非常简单的匹配单词,它是在O(m)中,使用例如Knuth-Morris-Pratt algorithm)。

答案 4 :(得分:1)

取决于实施。什么语言/图书馆/班级?可能是最好的情况,但它对实现中的功能数量非常具体。

答案 5 :(得分:0)

您可以通过构建非确定性有限自动机而不是DFA来交换空间以获得速度。这可以在线性时间内遍历。当然,在最坏的情况下,这可能需要O(2 ^ m)空间。我希望这种权衡是值得的。

答案 6 :(得分:0)

如果您在匹配和替换之后,则意味着分组和反向引用。

这是一个perl示例,其中分组和反向引用可用于解决NP完整问题:   http://perl.plover.com/NPC/NPC-3SAT.html

这(加上一些其他理论花絮)意味着使用正则表达式进行匹配和替换是NP完全的。

请注意,这与正则表达式的形式定义不同 - 它没有分组的概念 - 并且在多项式时间内匹配,如其他答案所述。

答案 7 :(得分:0)

在python的re库中,即使编译了正则表达式,在某些情况下,复杂度仍可能是指数级的(以字符串长度计),因为它不是基于DFA构建的。一些引用hereherehere