【问题标题】:converting CFG to regular expression将 CFG 转换为正则表达式
【发布时间】:2021-12-02 12:28:31
【问题描述】:

这是一个生成 0、1 或 0 和 1 的字符串的 CFG,其排列方式如下 (001, 011),其中一个字符的计数必须大于另一个字符,例如 0001111100000111

S → 0S1 | 0A | 0 | 1B | 1
A → 0A | 0
B → 1B | 1

我尝试使用此 guide 将其转换为正则表达式,但由于在该指南中找不到与它类似的任何内容,我无法转换 0S1,因此我被困在这里。

S → 0S1 | 0+ | 0 | 1+ | 1    
A → 0A | 0    = 0+
B → 1B | 1    = 1+

我之前的尝试之一是0+0+1|0+1+1|1+|0+,但它不接受我上面提到的字符串,例如0001111100000111

【问题讨论】:

  • 这可能听起来很尴尬,但我不知道你在说什么,
  • 是什么让您认为该语言是常规的?乍一看,这似乎不太可能(“常规语言不能算”)

标签: regex context-free-grammar context-free-language automata-theory


【解决方案1】:

即插即用

^(?!01$)(?!0011$)(?!000111$)(?!00001111$)(?=[01]{1,8}$)0*1*$

您无法将其完美地转换为正则表达式,但您可以通过确保输入不具有相同数量的 01 来接近。这最多匹配 8 位数字。

工作原理

  • ^首先你从一行的开头开始
  • (?!01$) 确保字符不是01
  • (?!0011$) 确保字符不是0011
  • 00011100001111 相同
  • 然后确保有从18 的零和一(这是必需的,以确保输入不是由更多的数字组成,例如000000111111,因为它们的对称性没有得到验证)
  • 然后匹配这些零和一直到行尾
  • 对于更长的输入,您需要添加更多文本,对于最多 10 位数字,它是这样的:^(?!01$)(?!0011$)(?!000111$)(?!00001111$)(?!0000011111$)(?=[01]{1,10}$)0*1*$(您可以通过添加一个对称验证来跳 2)
  • 仅使用正则表达式是无法通过其他方式实现的,请参阅说明。

说明

AB 很简单,正如您看到的 0+1+S 在第一个之后的连接也很容易:00+011+1,所有这些都混合在一起导致(0+|1+)。问题在于第一个串联0S1

所以问题可以简化为S = 0S1。这个语法是递归的。但是left linearright linear 都不是。要识别此语法的输入,您需要“记住”您找到了多少 0,以便能够匹配相同数量的 1,但从常规语法创建的有限状态机(通常和来自正则表达式)没有计算历史。它们只是状态和转换,机器从一种状态“跳跃”到另一种状态,不记得经过转换的“路径”。

因此,您需要更多强大的机器(如下推自动机),可以从上下文无关语法(如您的)构造。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 2016-04-02
    • 1970-01-01
    • 2019-05-11
    • 2014-11-08
    • 2017-12-29
    • 2023-03-09
    相关资源
    最近更新 更多