【问题标题】:Convert a NFA to Regular Expression将 NFA 转换为正则表达式
【发布时间】:2013-11-19 01:11:10
【问题描述】:

我在这个网站上发现了同样的问题,答案是PDF describing how to convert an NFA to a regex。但这不起作用,因为这种方法有一些条件:

  1. 存在从初始状态到所有其他状态的转换,并且没有 过渡到初始状态。
  2. 只有一个接受状态,只有转换进入它(并且没有传出 过渡)。
  3. 接受状态不同于初始状态。
  4. 除了初始状态和接受状态,所有其他状态都连接到所有其他状态 通过过渡状态。特别是,每个状态都有到自身的转换。

在我的示例中,开始状态只是进入下一个状态,而不是所有状态(例如 q0 进入 q1 但不进入 q2、q3),并且有到开始状态的转换。

那么将 NFA 转换为正则表达式的最简单方法是什么?我没有给出 NFA 示例,因为我没有一个特定的示例,这只是一个一般性问题,因为我遇到了这种 DFA,其中开始状态与所有状态不相关,并且是过渡到开始状态。

我想要一个通用算法来转换这种 NFA。

【问题讨论】:

  • 这个转换算法在乌尔曼自动机一书中有描述

标签: regex nfa


【解决方案1】:

答案是假设这些条件,因为任何 NFA 都可以修改以满足这些要求。

对于任何类型的 NFA,您都可以添加一个新的初始状态 q0,它对原始初始状态有一个 epsilon 转换,还可以使用一个称为 ∅ 的附加转换符号(他们称之为空集符号,假设是一个与原始 NFA 中的任何符号都不匹配的符号)从它到任何其他状态,然后使用这个新状态作为新的初始状态。请注意,这不会更改原始 NFA 接受的语言。这将使您的 NFA 满足第一个条件。

对于任何类型的 NFA,您都可以添加一个新的接受状态 qa,它具有来自原始 NFA 中所有接受状态的 epsilon-transition。然后将此标记为唯一的接受状态。请注意,这不会更改原始 NFA 接受的语言。这将使您的 NFA 满足第二个条件。

通过上述构造,通过设置q0 != qa,满足第三个条件。

在您提供的链接中,第四个条件通过一个特殊的转换符号来解释,称为 ∅(空集符号),原始 NFA 中的任何实际字母都无法与之匹配。因此,您可以使用这个新符号添加从每个状态到任何其他状态的转换。请注意,这不会更改原始 NFA 接受的语言。

所以现在 NFA 已经被修改为满足这四个要求,您可以应用那里的算法将 NFA 转换为正则表达式,它将接受与原始 NFA 相同的语言。

编辑以回答更多问题

要在评论中回答您的问题,请考虑具有两个状态的 NFA,qA 和 qB。 qA 是初始状态,也是唯一的接受状态。我们有一个从 qA 到符号 0,1 的转换。我们也有从 qA 到 qB 的转换,符号为 1。最后我们有从 qB 到 qA 的转换sub> 符号为 0。

可视化:

0,1 | 1 ->qA----->qB ^ | |-------| 0

Step 2. 当我们对 NFA 进行归一化时,只需放入指向 qA 的新 init 状态 (qinit),并放入新的接受状态 (q acc) 来自 qA.

第 3 步。我们要删除 qA。所以 qA 是算法中的 qrip(在第 3 页)。现在我们需要考虑进入 qA 的每个状态和退出 qA 的每个状态。在这种情况下,有两个状态指向 qA,即 qinit 和 qB。 qA 指向两个状态,即 qB 和 qacc。通过该算法,我们将转换 qin->qrip->qout 替换为转换 qin->qout,具有转换符号 Rdir+Rin(Rrip)*Rout,其中:

  1. Rdir 是从 qin 到 qout 的原始转换
  2. Rin 是从 qin 到 qrip 的原始转换
  3. Rrip 是 qrip 处的原始循环
  4. Rout 是从 qrip 到 qout 的原始转换

所以在这种情况下,我们将转换 qinit->qA->qB 替换为 qinit sub>->qB 带有转换符号 (0+1)*1。继续这个过程,我们将总共创建 4 个新的过渡:

  1. qinit->qB: (0+1)*1
  2. qinit->qacc: (0+1)*
  3. qB->qB: 0(0+1)*1
  4. qB->qacc: 0(0+1)*

那么我们可以去掉qA

第 4 步。我们要删除 qB。同样,我们确定了 qin 和 qout。这里只有一个状态来到qB,就是qinit,离开qB只有一个状态,就是qacc。所以我们有:

  1. R目录 = (0+1)*
  2. Rin = (0+1)*1
  3. Rrip = 0(0+1)*1
  4. R = 0(0+1)*

所以新的转换 qinit->qacc 将是:

Rdir+Rin(Rrip)*Rout

(0+1)* + (0+1)*1 (0(0+1)*1)* 0(0+1)*

我们可以删除qB

第 5 步。由于原始 NFA 中的每个状态都已被删除,因此我们完成了。所以最终的正则表达式如上所示。

请注意,最终的正则表达式可能不是最优的(在大多数情况下也不是最优的),这是算法所期望的。一般而言,为 NFA(甚至 DFA)找到最短的正则表达式非常困难(尽管对于这个示例,很容易看出第一个组件已经涵盖了所有可能的字符串)

为了完整起见,接受相同语言的最短正则表达式为:

(0+1)*

【讨论】:

  • 非常感谢您的回复。在我提供的网站上,2.1 示例:从 GNFA 到 8 个简单图形中的正则表达式,第一步删除状态 A,但是示例中的此状态在状态 A 上没有循环转换,如果我的 A 状态有循环转换怎么办超过?我必须把这个转换到 q0 (新的初始状态)?此外,如果一个状态将数据发送到旧的初始状态呢?
  • 例如,如果原始初始状态 qA,具有 0 和 1 的循环箭头,发送到 qB 1 并从 qB 0 接收,这会是什么样子?循环箭头将是 (0+1)* 和发送和接收 (01)* ?并且都从 NEW 初始状态发送到 qB 并带有一个转换,例如 (0+1)*(01)*?
猜你喜欢
  • 1970-01-01
  • 2012-05-30
  • 2012-03-01
  • 2013-08-01
  • 1970-01-01
  • 2010-10-18
  • 2012-12-26
  • 2013-10-28
  • 1970-01-01
相关资源
最近更新 更多