为什么正则表达式((x,y)|(x,z))是不确定的,正如“核心Java”这本书所说的那样?作者给出了他的观点:
当解析器看到x时,它不知道要采用哪两个替代方案。这个表达式可以以确定的形式重写为(x,(y | z))
有人可以给我一个解释吗?
答案 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,y
或x,z
(非确定性形式)
(X,(Y | Z))
在这种情况下,解析器可以阅读x,
,现在可以自由选择y
或z
(确定形式)
答案 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组中。