正则表达式 – 将NFA转换为正则表达式

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

>从初始状态到所有其他状态都有转换,但没有
过渡到初始状态.
>有一个接受状态只有转换进入它(没有传出
转换).
>接受状态与初始状态不同.
>除了初始状态和接受状态之外,所有其他状态都与所有其他状态相连
通过过渡国家.特别是,每个州都有自己的过渡.

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

那么将NFA转换为正则表达式的最简单方法是什么?我没有给出一个NFA示例,因为我没有特定的一个,只是一个普遍的问题,因为我遇到了这种DFA,其中启动状态与所有状态都没有关联,并且转换为开始状态.

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

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

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

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

通过上述结构,通过设置q0!= qa,它满足第三条件.

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

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

编辑以回答进一步的问题:

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

可视化:

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

步骤2.当我们规范化NFA时,只需将指向qA的新init状态(qinit)放入qA,然后从qA中设置新的接受状态(qacc).

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

> Rdir是从qin到qout的原始过渡
>凛是从琴到qrip的原始过渡
> Rrip是qrip的原始循环
> Rout是从qrip到qout的原始过渡

因此,在这种情况下,我们用qinit-> qB替换转换qinit-> qA-> qB,其中转换符号(0 1)* 1.继续这个过程,我们将创建总共4个新过渡:

> qinit-> qB:(0 1)* 1
> qinit-> qacc:(0 1)*
> qB-> qB:0(0 1)* 1
> qB-> qacc:0(0 1)*

然后我们可以删除qA.

第4步.我们要删除qB.再次,我们确定了qin和qout.这里只有一个州来到qB,这是qinit,并且只有一个州从qB离开,这是qacc.所以我们有:

> Rdir =(0 1)*
> Rin =(0 1)* 1
> Rrip = 0(0 1)* 1
> Rout = 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)*

点赞