正则到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. C#扫描仪编程、条形码识别编程资料

    扫描仪编程资料:http://www.cnblogs.com/wubh/archive/2011/11/07/2239178.html 图片条形码识别资料:http://www.codeproject ...

  2. Mathematics for Computer Graphics数学在计算机图形学中的应用 [转]

    最近严重感觉到数学知识的不足! http://bbs.gameres.com/showthread.asp?threadid=10509 [译]Mathematics for Computer Gra ...

  3. CloudStack4.2 更新全局参数

    { "updateconfigurationresponse": { "configuration": { "category": &quo ...

  4. 玩转iOS开发 - 多线程开发

    前言 本文主要介绍iOS多线程开发中使用的主要技术:NSOperation, GCD. NSThread, pthread. 内容依照开发中的优先推荐使用的顺序进行介绍,涉及多线程底层知识比較多的NS ...

  5. [ACM] hdu 1181 变形课

    变形课 Problem Description 呃......变形课上Harry碰到了一点小麻烦,由于他并不像Hermione那样可以记住全部的咒语而任意的将一个棒球变成刺猬什么的,可是他发现了变形咒 ...

  6. 关于c#中的Timer控件的简单用法

    Timer控件主要会用到2个属性一个是Enabled和IntervalEnabled主要是控制当前Timer控件是否可用timer1.Enabled=false;不可用timer1.Enabled=t ...

  7. JavaScript中事件捕获(Event capturing)-------------->由外向内,事件冒泡(Event bubblin)---------->由内向外

    addEventListener("click", function() {}, useCapture:false); <!DOCTYPE html> <html ...

  8. NBUT 1225 NEW RDSP MODE I

    找出循环周期即可了 #include<bits/stdc++.h> using namespace std; int N,M,X; int time(int x,int y,int z) ...

  9. MySQL执行SHOW STATUS查询服务器状态状态之Handler_read_* 详解

    在MySQL里,我们一般使用SHOW STATUS查询服务器状态,语法一般来说如下: SHOW [GLOBAL | SESSION] STATUS [LIKE ‘pattern’ | WHERE ex ...

  10. oralce 函数 FOR windows 跟踪神器

    https://github.com/dennis714 http://www.yurichev.com