最近得做一些跟自动机有关的东東其中一部分可以简要地看作是由一套正则文法生成状态自动机的过程。
首先我们看看什么是这个东东呢,一般用于描述一个字符串嘚集合——直接说就是一个正则表达式转换可能可以匹配一大堆字符串而这一大堆字符串可以形成一个集合,它们的共同特征就是可以被这个正则表达式转换匹配就像去死去死团,但是不同的是去死去死团的团员的共同特征是不被任何异性所匹配——但是这没关系我們不妨取去死去死团的补集就行了。
反正正则表达是很好啦因为你只要用一点点在脏话里,就可以骂好多好多人比如:
真是非常de省力,唯一的缺点是可能对方不知道你在说什么
好了,从上面我们可以看出正则表达式转换中的两个基本结构:
下面是第三个基本结构被稱为 (或者 Kleene 闭包)的。因为这个操作是发明的啊啊,其实正则表达式转换这个东西就是Kleene发明的这个同学真是非常的牛B,因为他是更加牛B的 阿隆佐 - 丘奇 ( Alonzo Church )——历史上和阿兰 - 图灵 ( Alan Turing )
并称的人物——的学生有多牛B呢,这个Kleene还和他的老师还有图灵,就递归论发表了论文奠定了可计算理论的根基。啊哈哈哈真是牛B啊。
嗯所谓Kleene Star的例子就是这样的。
- Kleene Star比如a*,可以接受空串和若干个a连结组成的串
当然咯还有一些别的操作,比如我们知道的+?,集合[]等等但是这些操作都可以通过上面三个基本操作的组合来完成。
比如+a+可以认为是aa*
要说NFA嘛,我得先说说DFA所谓DFA,就是的简称是状态机的一种。通俗的说就是一大堆状态的集合,里面有一个初始状态和若干终止状态每个状态可以有若干個输出边前往别的状态。但是要求每个状态的同一种输出边至多只有一个所以自动机被称为是”Deterministic”的。
表述的是一个电灯de开关这个开關每按一下就从’开’状态转换到’关’状态,或者从’关’状态转换到’开’状态而为了从环保角度出发,在’关’状态才被认为是終止态
上面的自动机呢,就可以描述这个灯泡的行为模式或者说可以描述电灯的状态转换过程。输出边就是’开’或者’关’的动作或者说这个灯泡的开关,只接受这两种动作:“Trun On”“Trun Off”。而”Trun On”动作只会导致灯的状态变成“On”“Trun
Off”动作只会导致灯的状态变成“Off”,这是确定的你的外婆都可以预料到的。所以说DFA是确定有限状态自动机
现在可以说NFA了。这个NFA嘛全称是Non-deterministic Finite state Automata。也是状态自动机的一种確切地说,刚才的DFA是NFA的一个子集和DFA唯一的区别就是他是”Non-deterministic”的,哈非确定的,每个状态的同一种输出边可以不止一个
还是用刚才的唎子。现在假设我们的电灯有一种新的状态咯~:坏掉了灯丝被过大的电流烧断了,听上去遭透了因为一”Trun On”就得准备换灯泡了:
但昰我们没法确定的知道哪一次Trun On会导致灯泡坏掉,使得灯泡进入”Down”状态的那次“开”操作看上去跟你昨天开灯的那次操作一模一样(严格嘚说每一次点亮灯泡都会导致灯丝的状态发生变化,但是在此简化了)
所以从状态”Off”出来的输出边中”Trun On”有两条,这就导致没法根據当前状态和输出边确定下一状态这就是为什么称为非确定性有限自动机的原因。
刚才说了正则表达式转换有三种基本结构。如果能先将这三种基本结构转换成对应的NFA然后在用这三种基本结构去拼装成完整的NFA是不是很省力呢?
下面就是三种基本正则表达式转换的NFA
里面絀现了一种叫“None”的边这个不代表这个边是字面上的“None”,而是指这个边是个空边也就是说任何“动作”都可以从这个边进入下一个狀态。它的学名叫 epsilon 边一般表示成’ε’,这里表示成“None”了。
下面我们来考虑正则表达式转换到NFA转换给出一个正则串的输入,得到一個NFA的输出被广泛采用的是Thompson Algorithm,也就是所谓的子集算法该算法的发明人应该就是写ed编辑器的那个。该算法的实现和算术表达式的求值非常嘚类似需要一个符号栈存放操作符,一个自动机栈存放生成的自动机算法结束后,可以从自动机栈中Pop一个最终的结果
比如对于正则表达式转换(a|b)*cd,求值过程如下:
里面的UNIONSTAR 和 CONCAT就是三种基本结构的生成操作了。而这三种基本操作的实现是这样的:
|