正则到nfabug的解决方法

前面提到了这个bug,为了解决这个bug,我们必须在每次引用到一个假名的时候,都构建一个拷贝。现在假设我们遇到了一个假名,并得到了他的开始节点和结束节点,当前的难题就是构造这个假名所代表的nfa的副本。构造方法类似于子集构造法,我们设立一个集合,这个集合为R,集合中的每个元素都有一个标志位为访问位。初始化R为开始节点a,并让他的访问位为0。现在开始进入迭代,只要R中存在访问位为0的点,将他的访问位改为1,然后将他的邻接表中的点都加入到R中。加入的时候,考虑R中是否已经存在这个元素,如果已经存在,则不加入。如果不存在,则加入,并设置访问位为0。然后返回迭代判断。

最后当R中的元素不再增加的时候,为每一个元素设置一个新的节点,即对于每个元素a,都有一个f(a)与之对应。为f(a)设置邻接表,就是a的邻接表的拷贝,但是里面的目标地址b都变成了f(b)。这样我们就完成了nfa图的复制工作。由于有集合操作,主要任务为插入和查找,所以实现的时候考虑建立一个散列表,采取开放寻址的线性探查,来加速操作。

但是,如果我们证明了,任何一个假名的nfa节点的标号集合是一个连续的整数区间的话,我们就可以以非常高的效率来做到nfa图的复制。下面我们就来证明一个nfa图里面所有的标号刚好完全占据了一个整数区间,而这个证明需要数学归纳法。我们对一个正则表达式里面的假名嵌套深度来归纳。设s为嵌套深度。

当s为零的时候,即表达式里面没有引用。这个时候考虑我们在分配nfa节点时候的分配策略,我们保留了一个全局的nfa_node_number,每分配一个节点,这个就加1,然后把这个值当作节点的标号,这些节点都是一个一个连续分配的,而且他们没有进入的边,也没有出去的边。所以我们可以为这个正则表达式附加他的最小标号节点和最大标号节点,这样就可以避免集合操作,因为这之中的点都属于该正则表达式。而且这样在重新映射的时候,映射函数可以改为线性函数,直接采用加法规则就可以了。

现在考虑s为1的时候,即正则表达式中拥有一个s为0的假名的引用。由于nfa_node_number是全局的,我们考虑刚开始进入这个正则表达式的时候,可用的标号为a,当进入这个引用时,可用标号为b,即在拷贝nfa图的时候引起的节点分配是以b开始的。由于进行拷贝nfa图的时候,节点分配是连续的,假设拷贝完之后,可用标号为c,则b-c之间的标号都被使用了。由于a-b之间的标号都被使用了,所以a-c之间的标号也是都被使用了,因此a-c之间是连续的,并一直向右扩展,当这个正则表达式处理完的时候,可用标号为d,则a-d之间的标号都被这个正则表达式使用了,因此我们也可以设置这个正则表达式的开始标号与结束标号 。

虽然我们当前讨论的是不怎么严格的数学归纳,但是我们可以从上面的讨论可以看出,每一个假名所代表的正则表达式都有他的起始标号和结束标号,而且之间的标号都是被这个正则表达式所使用的,外部标号的节点不会跟这些标号的节点相连。因此我们可以将这两个域添加到这个假名的信息里面去。

我将用代码来描述如何维护这些信息,以及利用这些信息来做nfa图的复制。

正则转nfa:bug消除的更多相关文章

  1. 正则转nfa:bug出现。

    本人写的一个正则到nfa的bug 刚写完前面的那篇,自己用脑子过了一下,发现了一个bug.具体情况如下. 这个bug的产生条件是多次调用假名的时候,每次调用都会修改假名的nfa图.直接这么说不好理解, ...

  2. 正则转nfa:完成

    太累了,感觉不会再爱了.问题已经解决,具体的懒得说了. #include "regular_preprocess.h" //这个版本终于要上nfa了,好兴奋啊 //由于连个节点之间 ...

  3. 最初步的正则表达式引擎:nfa的转换规则。

    [在此处输入文章标题] 正则到nfa 前言 在写代码的过程中,本来还想根据龙书上的说明来实现re到nfa的转换.可是写代码的时候发现,根据课本来会生成很多的无用过渡节点和空转换边,需要许多的代码.为了 ...

  4. Bug驱动开发(Bug-driven development)

    说实话,作为一个Domino开发者,像測试驱动开发(Test-driven development).功能驱动开发(Feature-driven development)之类软件开发的高大上的方法论( ...

  5. 正则表达式引擎:nfa的转换规则。

    正则表达式引擎:nfa的转换规则. 正则到nfa 前言 在写代码的过程中,本来还想根据龙书上的说明来实现re到nfa的转换.可是写代码的时候发现,根据课本来会生成很多的无用过渡节点和空转换边,需要许多 ...

  6. NFA/DFA算法

    1.问题概述 随着计算机语言的结构越来越复杂,为了开发优秀的编译器,人们已经渐渐感到将词 法分析独立出来做研究的重要性.不过词法分析器的作用却不限于此.回想一下我们的老师刚刚开始向我们讲述程序设计的时 ...

  7. 使用方便 正则表达式grep,sed,awk(一)

    一些无稽之谈: 对于正则表达式,永远似了解不明白,看到一些代码,脚本定期,awk,sed.心里总有点虚.主要是记不住.平时又没怎么用,也就没总结了. 如今有空,决定总结一下,顺便克服一下看到shell ...

  8. LinbDesk --- 新的extjs4.2 desktop demo : 技术交流Q群:336584192

    很多朋友对extjs desktop感兴趣,就在原来简单的dsktop基础上,作了很多拓展  主要例如以下: 软件更新情况介绍: LinbDesk 拓展自Extjs 4.2的桌面Demo 拓展代码适用 ...

  9. 第一周Python学习笔记

    Python 基本语法: ①  Python程序的格式:1.用代码高亮来标识函数丶语句等等 本身的代码高亮并没有实际的意义,只是用来辅助编程人员和阅读人员 更好的识别 2.程序以缩进来标识语句,缩进用 ...

随机推荐

  1. My集合框架第三弹 AVL树

    旋转操作: 由于任意一个结点最多只有两个儿子,所以当高度不平衡时,只可能是以下四种情况造成的: 1. 对该结点的左儿子的左子树进行了一次插入. 2. 对该结点的左儿子的右子树进行了一次插入. 3. 对 ...

  2. JVM启动参数小结

    一:JVM启动参数共分为三类:         其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容:        其二是非标准参数(-X),指的是JVM底层的一些配置参数, ...

  3. 集成StyleCop到Jenkins CI

    这是集成完stylecop之后的Jenkins,可以看到code review结果随每个build变化的图表,Build History里面可以看到#150之前的build状态是unstable,这是 ...

  4. 【转】Android TouchEvent事件传递机制

    Android TouchEvent事件传递机制   事件机制参考地址: http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html ht ...

  5. strlen与sizeof的区别 [转]

    转自:http://www.cppblog.com/liangbo/archive/2006/10/06/13394.html 1.sizeof操作符的结果类型是size_t,它在头文件中typede ...

  6. JavaScript要点(十七) Math 对象

    来源:JavaScript 参考手册 Math 对象 Math 对象用于执行数学任务. Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(). 语法 var ...

  7. JAVA核心技术--继承

    1.继承:向上追溯,对同一批类的抽象,延续和扩展父类的一切信息! 1)关键字:extends      例如,父类是Animal,子类是Dog;   eg: public class Dog exte ...

  8. C#完成超酷的图像效果 (附demo)

    如果您觉得C#制作的艺术字比较好玩, 但是还觉得没看够,不过瘾,那么我今天就让您一饱眼福, 看看C#如何制作的效果超酷的图像. (注: 我之前曾写过类似的文章, 但没有原理说明, 代码注释不够详细, ...

  9. MySQL 4种日志

  10. 【WebForm】Js调用后台C#方法

    因业务的需要,有这么个需求,需要前台的JS传参调用C#后台的方法.现在有这么个方法可以解决,整理如下. 首先,先说一下基本实现,前台用Jquery的ajax将其中的URL后加方法,然后在Data中传递 ...