我有一组正则表达式,想要分析它们以确定是否存在一个字符串能匹配超过1个正则表达式。除了为此编写自己的正则表达式引擎之外,是否有一种在C++或Python中解决这个问题的简单方法?
我有一组正则表达式,想要分析它们以确定是否存在一个字符串能匹配超过1个正则表达式。除了为此编写自己的正则表达式引擎之外,是否有一种在C++或Python中解决这个问题的简单方法?
没有简单的方法。
只要你的正则表达式仅使用标准功能(我想Perl允许您嵌入匹配的任意代码),您就可以从每个正则表达式中产生一个非确定性有限状态自动机(NFA),它紧密地编码了正则表达式匹配的所有字符串。
对于任何一对NFA,都可以确定它们的交集是否为空。如果交集不为空,则某些字符串同时匹配该对RE中的两个RE(反之亦然)。
标准可判定性证明是将它们确定为DFA,然后构造一个新的DFA,其状态是两个DFA状态的组合,并且其最终状态恰好是原始DFA中两个状态均为最终状态的状态。或者,如果您已经展示了如何计算NFA的补集,则可以通过DeMorgan的定律样式得到交集:complement(union(complement(A),complement(B)))
。
不幸的是,NFA->DFA涉及潜在的指数级爆炸(因为DFA中的状态是NFA中状态的子集)。来自Wikipedia:
顺便提一下,你绝对应该使用OpenFST。你可以创建文本文件作为自动机,并在其中进行操作,如最小化、交集等等,以查看它们对您的问题的效率如何。已经存在开源regexp->nfa->dfa编译器(我记得有一个Perl模块);修改其中一个以输出OpenFST自动机文件并进行操作。某些正则语言类只能由大小呈指数级增长的确定性有限自动机描述,这里的标准示例是L_k语言,该语言由符号集{a,b}上所有k次最后一次字母等于a的字符串组成。
A ->a B
(您可以从状态A到B输出字母'a'),并且在另一个NFA中 X ->a Y
,则在交集中(A,X) ->a (B,Y)
。(C,Z)
是最终状态。(A,X)
- 这是交集-NFA的起始状态。每次访问一个状态时,根据上述规则为每对离开两个状态的弧生成一个弧,然后访问这些弧到达的所有(新)状态。您将存储您扩展状态的弧(例如在哈希表中),并最终探索从起点可以到达的所有状态。A ->epsilon B
,则对于每个您到达的状态(A,Y)
,添加弧(A,Y) ->epsilon (B,Y)
,类似地,在第二个位置的NFA中也是如此。在将正则表达式转换为NFA时,使用epsilon转换对于取两个NFAs的并集是有用的(但不是必需的); 每当您有交替 regexp1|regexp2|regexp3
时,都会进行并集操作:一个起始状态具有到代表交替中的每个正则表达式的NFA的epsilon转换的NFA。
决定NFA是否为空很容易:如果您从起始状态开始进行深度优先搜索并到达终止状态,则它不为空。
该NFA交集类似于有限状态转换器组合(转换器是一种输出符号对的NFA,这些符号成对连接以匹配输入和输出字符串,或将给定输入转换为输出)。
从理论上讲,您所描述的问题是不可能的。
在实践中,如果您有一些可管理的正则表达式数量,这些正则表达式使用有限的子集或regexp语法和/或有限的字符串选择来匹配正则表达式容器,那么您可能能够解决它。
假设您不是试图解决抽象的一般情况,那么可能有一些方法可以解决实际应用。也许,如果您提供正则表达式的代表性样本,并描述要匹配的字符串,就可以创建一个启发式算法来解决问题。