[在此处输入文章标题]
在写代码的过程中,本来还想根据龙书上的说明来实现re到nfa的转换。可是写代码的时候发现,根据课本来会生成很多的无用过渡节点和空转换边,需要许多的代码。为了简化代码,我实现了我自己的re到nfa的规则。
注意我的这套re规则只包括如下几种类型:
在谈及如何将re转换为nfa的时候,我将先把最常见的三种运算符讲解一下,然后再是其他的那几种模式的转换。
注意,在转换re的时候,我们假设已经得到了子re的开始节点和结束节点,我们需要做的就是根绝这些开始节点和结束节点来构造当前re的开始节点和结束节点。
以A:b*这个表达式来说明
这里的开始节点是b的开始节点,结束节点是b的结束节点。构造a的nfa的时候,只需要添加两条空转换边,然后将b的开始节点赋给a的开始节点,同时b的结束节点复制到a的结束节点去。总的代价是建立了两条空边。
龙书中,而外的建立了两个新的节点分别当作新的开始节点和结束节点,并且总共添加了四条空转换边。
在处理连接运算的时候,我跟龙书里面的处理是以致的。以a:bc来说明。
这里只添加了一条新的空转换,没有新增加节点。A的开始为b的开始节点,a的结束为c的结束节点。
在处理选择运算的时候,跟龙书也是一致的。以a:b|c来说明。
这里也是新建了两个节点,作为新的开始与结束节点,然后增加了四条空转换边。
这里龙书并没有提及,在我的实现中只增加了一个节点。以a:b+来说明。
新建了一个节点作为a的结束节点,而b的开始节点也直接符给a的开始节点,添加了两个空转换。
这里龙书也没有提及,在我的实现中只增加了一条边。以a:b?来说明。
B的开始节点赋给a的开始节点,b的结束节点赋给a的结束节点。
对于简单字符,我这里的实现是新建两个节点,以及一条边。以a:b来说明。
由于b是字符,所以他不存在开始节点和结束节点,字符只能作为转换条件。新建两个节点,一个作为a的开始节点,一个作为a的结束节点,然后在两个节点之间建立一条标为b的边。
对于字符集,本人的实现是新建两个节点,然后每一个字符对应一条边来加入。
以a:b-d来说明。
因此,总共增加了两个节点和三条边。字符集里面有多少个字符,就会有多少条边。
对于括号及假名,直接把子表达式的开始节点和结束节点复制到当前表达式的开始节点和结束节点,不需要额外的处理。
自我感觉这些都是对的,当然要验证对错得等到最小化dfa才能证明。