Regex 如何确定一个正则表达式是否与另一个正则表达式正交?
我想我的问题最好用一个(简化的)例子来解释 正则表达式1:Regex 如何确定一个正则表达式是否与另一个正则表达式正交?,regex,fsm,Regex,Fsm,我想我的问题最好用一个(简化的)例子来解释 正则表达式1: ^\d+_[a-z]+$ 正则表达式2: ^\d*$ 正则表达式1永远不会匹配正则表达式2匹配的字符串。 假设正则表达式1与正则表达式2正交 正如许多人问我所说的正交是什么意思,我将试图澄清: 设S1为正则表达式1匹配的(无限)字符串集。 S2是正则表达式2匹配的字符串集。 当S1和S2的交点为空时,正则表达式2与正则表达式1正交。 regex^\d_a$将不是正交的,因为字符串“2_a”在集合S1和S2中 如果两个正则表达式彼此正
^\d+_[a-z]+$
正则表达式2:
^\d*$
正则表达式1永远不会匹配正则表达式2匹配的字符串。
假设正则表达式1与正则表达式2正交
正如许多人问我所说的正交是什么意思,我将试图澄清:
设S1为正则表达式1匹配的(无限)字符串集。
S2是正则表达式2匹配的字符串集。
当S1和S2的交点为空时,正则表达式2与正则表达式1正交。
regex^\d_a$将不是正交的,因为字符串“2_a”在集合S1和S2中
如果两个正则表达式彼此正交,如何通过编程确定
最好的情况是实现以下方法的库:
/**
* @return True if the regex is orthogonal (i.e. "intersection is empty"), False otherwise or Null if it can't be determined
*/
public Boolean isRegexOrthogonal(Pattern regex1, Pattern regex2);
您可以使用类似的方法生成与指定正则表达式匹配的测试字符串,然后使用第二个正则表达式上的测试字符串来确定这两个正则表达式是否正交。在某些情况下,证明一个正则表达式与另一个正则表达式正交可能很简单,例如,在相同位置的互斥字符组。对于除最简单的正则表达式之外的任何正则表达式来说,这都是一个非常重要的问题。对于严肃的表达,包括分组和反向引用,我甚至认为这可能是不可能的。所谓“正交”你的意思是“交叉点是空集”,我认为是吗 我会为交集构造正则表达式,然后转换成正规形式的正则语法,看看它是否是空语言 再说一遍,我是一个理论家…我相信你用正交法来表示是正确的。
这是正确的吗?首先让我说,我不知道如何构造这样一个算法,也不知道有哪个库实现了它。然而,如果知道任意复杂的一般正则表达式不存在这样的情况,我一点也不会感到惊讶 每一个正则表达式都定义了一种正则语言,它包含了该表达式可以生成的所有字符串,或者如果您愿意的话,还定义了所有与正则表达式“匹配”的字符串。将语言视为一组字符串。在大多数情况下,集合将无限大。您的问题是,正则表达式给出的两个集合的交点是否为空 至少在一级近似下,我无法想象一种不计算集合的方法来回答这个问题,而对于无限集合,计算集合的时间会比你想象的要长。我认为可能有一种方法可以计算一个有限的集合,并确定什么时候在其他正则表达式所要求的范围之外详细描述一个模式,但这并不简单
例如,只需考虑简单表达式<代码>(ab)*< /COD>和<代码>(ABA)*B<代码>。什么算法会决定从第一个表达式生成
abab
,然后停止,而不检查abababab
,abababab
等,因为它们永远不会工作?您不能只生成字符串并检查,直到找到匹配项,因为当语言不相交时,这将永远不会完成。我无法想象在一般情况下会有什么效果,但在这方面有比我更好的人
总而言之,这是一个难题。如果我知道有多项式时间的解,我会有点惊讶,如果我知道它等价于停顿问题,我也不会感到惊讶。虽然,鉴于正则表达式不是图灵完全的,但似乎至少有可能存在一个解决方案。我将执行以下操作:
- 使用如下结构将每个正则表达式转换为FSA:
struct FSANode { bool accept; Map<char, FSANode> links; } List<FSANode> nodes; FSANode start;
struct { 布尔接受; 地图链接; } 列出节点; 阳极启动;
- 创建一个新的组合节点,如:
class CombinedNode { CombinedNode(FSANode left, FSANode right) { this.left = left; this.right = right; } Map<char, CombinedNode> links; bool valid { get { return !left.accept || !right.accept; } } public FSANode left; public FSANode right; }
类组合节点 { 组合节点(左FSANode,右FSANode) { this.left=左; 这个。右=右; } 地图链接; bool valid{get{return!left.accept | | |!right.accept;}} 公营部门:左派; 公权力; }
$ ./binaries/osx/genex '^\d+_[a-z]+$' '^\d*$'
$
$ runghc Main.hs '\d' '[123abc]'
1.00000000 "2"
1.00000000 "3"
1.00000000 "1"
/**
* @return true if the two regexes will never both match a given string
*/
public boolean isRegexOrthogonal( String regex1, String regex2 ) {
Automaton automaton1 = new RegExp(regex1).toAutomaton();
Automaton automaton2 = new RegExp(regex2).toAutomaton();
return automaton1.intersection(automaton2).isEmpty();
}