为什么正则表达式((x,y)|(x,z))是不确定的?

时间:2015-11-24 13:56:52

标签: java regex

为什么正则表达式((x,y)|(x,z))是不确定的,正如“核心Java”这本书所说的那样?作者给出了他的观点:

  

当解析器看到x时,它不知道要采用哪两个替代方案。这个表达式可以以确定的形式重写为(x,(y | z))

有人可以给我一个解释吗?

4 个答案:

答案 0 :(得分:10)

要获得确定性表单,您只能在当前位置最多使用一种方法。我们假设您有一个字符串" x,y "。现在,正则表达式引擎会查看第一个字符," x "。在你的表达式中,你有两种可能性,你的字符串可以在" x "之后继续。在第一个位置接受你的意见。接下来有2种方法可供检查。如果字符串后跟" ,y "或者通过" ,z "。

   , ⇨ y
 ⬀
x
 ⬂
   , ⇨ z

对于(x,(y | z)),你总是只有一种方式。如果" x "位于第1位,你进入位置2.同样,只需使用" "。最后他必须检查是否有" y "或者" z "在第3位接受这个词。从来没有两种方式。

x ⇨ , ⇨ (y or z)

答案 1 :(得分:2)

有限状态机称为非确定性有限自动机(NFA),if 给定一个特定的状态,它可以有多个具有相同符号的转换

这意味着你的语法(即你的正则表达式)可以导致同一个表达式有2个派生树,我们不知道自动机将要选择的状态:

       x 
      / \
     /   \
    /     \
   ,       ,
   |       |
   |       | 
   y       z

答案 2 :(得分:0)

  

((X,Y)|(X,Z))

在这种情况下,当解析器看到x时,它不知道要采用哪个组,即x,yx,z(非确定性形式)

  

(X,(Y | Z))

在这种情况下,解析器可以阅读x,,现在可以自由选择yz(确定形式)

答案 3 :(得分:0)

我认为上述问题仅在涉及群组匹配时才有意义。

如果x是([a-z][a-z])而y是([0-6][0-6])而z是([3-9][3-9]),那么你有一个像这样的正则表达式:

((([a-z][a-z]),([0-6][0-6]))|(([a-z][a-z]),([3-9][3-9])))

给定像pq,45这样的输入,这可以与管道符号的任一侧匹配(即它匹配(([a-z][a-z]),([0-6][0-6])) (([a-z][a-z]),([3-9][3-9])))。

在这种情况下,标准定义管道符号的左侧在右侧之前具有首选项。 x的值可以在组号3中找到(第三个左括号)。

如果输入现在变为e。 G。 pq,78,然后x的匹配根本没有改变(它仍然是pq)但现在管道符号的右侧匹配,你会发现x的值为第6组。

这可以通过使用更稳定的正则表达式来避免,例如(([a-z][a-z]),(([0-6][0-6])|([3-9][3-9]))),其中x总是在第2组中。