正则表达式等价

Posted

技术标签:

【中文标题】正则表达式等价【英文标题】:Regular expressions Equivalence 【发布时间】:2010-10-08 07:09:09 【问题描述】:

有没有办法找出两个任意正则表达式是否等价?对我来说看起来很复杂,但可能有一些 DFA 简化机制之类的?

【问题讨论】:

【参考方案1】:

要测试等价性,您可以计算表达式的 minimal DFAs 并进行比较。

【讨论】:

比较两个 DFA 是什么意思?图同构? 因为你有一个初始状态并且转换被标记和确定,所以很容易检查 DFA 的相等性,比图同构容易得多。一次深度优先遍历就足够了。 @starblue 很棒的链接!【参考方案2】:

等式的可测试性是正则表达式的经典属性之一。 (注意,如果您真的在谈论 Perl 正则表达式或其他一些技术上的非正则超级语言,这并不成立。)

将您的 RE 转换为广义有限自动机 A 和 B,然后构造一个新的自动机 A-B,使得 A 的接受状态具有到 B 的起始状态的零转换,并且 B 的接受状态被反转。这给了你一个自动机,它接受 A 接受的所有字符串,除了 B 接受的所有字符串。

对 B-A 做同样的事情,并将两者都简化为纯 FA。如果 FA 没有可从起始状态访问的接受状态,则它接受空语言。如果你能证明 A-B 和 B-A 都是空的,那么你就证明了 A = B。

Edit 呵呵,我不敢相信没有人注意到那里的巨大错误——当然是故意的:-p

所描述的自动机 A-B 将接受前半部分被 A 接受而后半部分不被 B 接受的字符串。构建 所需的 A-B 是一个稍微棘手的过程。我无法想到它,但我确实知道它是明确定义的(并且可能涉及创建状态以表示 A 中的接受状态和 B 中的非接受状态的产物)。

【讨论】:

对于 A-B,您想使用交集和补码,不幸的是,这在正则表达式库中并不常见,尽管它们可以用于“真正的”正则表达式(而不是 Perl 类型)。 (也没有测试正则表达式是否不接受任何内容。库很糟糕,不是吗?)【参考方案3】:

这实际上取决于您所说的正则表达式的含义。正如其他发帖者所指出的那样,将这两个表达式都减少到它们的最小 DFA 应该是可行的,但它只适用于纯正则表达式。

现实世界的正则表达式库中使用的一些结构(尤其是反向引用)赋予它们表达非正则语言的能力,因此 DFA 算法不适用于它们。例如,正则表达式:([a-z]*) \1 匹配由空格分隔的相同单词的两次出现(a ab b,但不匹配 b aa b)。这是有限自动机根本无法识别的。

【讨论】:

【参考方案4】:

这两个 Perlmonks 线程讨论了这个问题(具体来说,请阅读 blokhead 的回复):

Comparative satisfiability of regexps Testing regex equivalence

【讨论】:

以上是关于正则表达式等价的主要内容,如果未能解决你的问题,请参考以下文章

正则个人总结

Java正则表达式中\w和\b的Unicode等价物?

python:非正则表达式等价于 re.findall

怎么设置正则表达式不区分大小写

JAVA正则表达式

正则表达式学习和常用正则验证规则(包括用户名,密码,手机号,网址等)