除了a * ..或bb ..之类的任意数量的字符串和字符串之外,正则表达式(a * + b *)是否包含类似
的字符串AB
或以b结尾的任何字符串
(a * + b *)是否与(a * b *)相同?
我对正则表达式(a * + b *)生成的字符串有点困惑,如果有人可以提供帮助,我会非常感激。
答案 0 :(得分:4)
除非您正在使用一种正则表达式语言,该语言明确地将*+
分类为具有特殊含义的特殊标记,或者为将来的扩展保留(并且现在产生定义的行为,或语法错误) ,a*+
的自然解析是(a*)+
:后缀+
应用于表达式a*
。
如果该解释适用,接下来我们可以观察到(a*)+
等同于a*
。因此a*+b*
与a*b*
相同。
首先,根据定义,R+
表示RR*
。匹配一个R
,然后匹配零个或多个。因此,我们可以将(a*)+
重写为(a*)(a*)*
。
其次,*
是幂等的,因此(a*)*
只是(a*)
。如果我们匹配“零或更多a
”,零次或多次,则没有任何变化;净效应为零或更多a
。 证明: R*
表示无限扩展:(|R|RR|RRR|RRRR|RRRRR|...)
:不匹配,或匹配一个R
,或匹配两个R
,...因此,(a*)*
拒绝这种扩展:(|a*|a*a*|a*a*a*|...)
。这些内部a*
- s反过来表示单个二级扩展:(|(|a|aa|aaa|...|)|(|a|aa|aaa|...)(a|a|aaa|...))|...)
。通过分支|
的关联属性,我们可以将(a|(b|c))
之类的结构展平为(a|b|c)
,当我们对扩展进行此操作时,我们注意到有许多相同的术语 - 空正则表达式()
,单a
,双aa
等等。这些都减少为单个副本,因为(|||)
等同于()
而(a|a|a|a|...)
等同于(a)
,依此类推。也就是说,当我们通过增加长度对术语进行排序,并将多个相同的术语压缩到一个副本时,我们最终会得到(|a|aa|aaa|aaaa|...)
,这可以被认为是a*
的扩展。因此(a*)*
为a*
。
最后,(a*)(a*)
仅表示a*
。 证明:与之前类似,我们扩展到分支机构:(|a|aa|aaa|...)(|a|aa|aaa|...)
。接下来我们注意到分支表达式的连接等同于这些术语的笛卡尔积集。也就是说(a|b|c|..)(i|j|k|...)
的意思是:(ai|aj|ik|...|bi|bj|bk|...|ci|cj|ck|...|...)
。当我们将此产品应用于(|a|aa|aaa|...)(|a|aa|aaa|...)
时,我们会收到越来越多的术语,这些术语在按照不断增加的长度排列并进行重复数据删除时,会减少到(|a|aa|aaa|aaaa|...)
,而这只是a*
。
答案 1 :(得分:1)
我认为这有助于查看正则表达式的正式定义,即查找语言L(e)所产生的每个正则表达式。
让我们开始简单:
(1) 正则表达式 a (只有字母)怎么样?它的语言是
L(a) := {a},
只是单个单词/字符“a”。
(2) 对于正则表达式 e1 + e2 ,其中e1和e2本身就是正则表达式,
L(e1 + e2) := L(e1) U L(e2).
所以,例如如果a和b是字符,则L(a + b)= {a,b}。
(3) 对于正则表达式 e1 e2 (连接),其中e1和e2本身是正则表达式,
L(e1 e2) := all words w such that
we can write w = w_1w_2 with w_1 in L(e1) and w_2 in L(e2)".
(4) 那么正则表达式* e **,其中e可能是正则表达式本身?直观地,如果单词具有形式,则在L(e *)中 w_1 w_w_3w_4 ... w_n,每个i的L(e)中有w_i。 所以
L(e*) := all words w such that we can write
w = w_1 w_2 .. w_n
for a n >= 0 with all w_i in L(e) (for i = 1, 2, ..., n)
那么,L((a * + b *))怎么样?
L((a* + b*))
(according to rule 2)
= L(a*) U L(b*)
(according to rule 4/1)
= {eps, a, aa, aaa, aaaa, ....} U {eps, b, bb, bbb, bbbb}
= all strings that have either only a's OR only b's in it
(including eps, the so-called empty word)
类似于(a * b *):
L((a* b*))
(according to rule 3)
= all words w = w_1 w_2 with w_1 in L(a*) and w_2 in L(b*)
= {eps eps, eps b, a eps, ab, aa eps, aab, ...}
= {eps, b, a, ab, aa, aab, aabb, ... }
= all strings that first have zero or more a's, then zero or more b's.
一开始我认为正如我们上面所做的那样,“解构”正则表达式会有所帮助 - 因为正则表达式也可以看作树,就像更常见的算术表达式一样,例如:
+
/ \
* *
| |
a b