(a * + b *)生成的字符串类型是什么

时间:2015-12-12 14:06:30

标签: regex compiler-construction computation-theory

除了a * ..或bb ..之类的任意数量的字符串和字符串之外,正则表达式(a * + b *)是否包含类似

的字符串
  

AB

或以b结尾的任何字符串

(a * + b *)是否与(a * b *)相同?

我对正则表达式(a * + b *)生成的字符串有点困惑,如果有人可以提供帮助,我会非常感激。

2 个答案:

答案 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