目前 febird 中的自动机库已支持正则表达式,而且,支持的是多正则表达式匹配:正则表达式
给定 M 个正则表达式,每一个正则表达式有一个 [0, M) 的惟一 ID,该算法为这些正则表达式生成一个 DFA。算法
再给定一个输入文本 Text,长度为 T,假定只计最长匹配,该 Text 能够匹配 M 个正则表达式中的的 K 个。服务器
在该DFA上运行个人匹配算法,能够在 O(T + K) 的时间复杂度内找到那 K 个正则表达式,这个时间复杂度与 M 彻底没有关系!从信息论的角度讲,该算法是最优的。数据结构
若是要得到在 Text 中的全部 N 个匹配点(N<=T),所要的时间是 O(T + K1 + ... Kn)),其中 Ki 表示第 i 个匹配点能匹配的正则表达式数目。工具
这也许是现存的最高效的解决该问题的算法,以前我一直认为该问题很难解决:一个很难的字符串问题,如今,它解决了,世界平静了!优化
当初我提出该问题的时候,若是我那个时候就开始尝试解决它,也许永远解决不了!ui
该问题的最终解决,倒是源于另外几个问题的解决,当我完美高效地实现DAWG以后,我就在想一个问题:如何实现一个动态的基于 DAWG 的 Map ?在 自动机的一些算法和应用 中,我想象了一个解决方案(相似红黑树索引号),可是后来通过仔细的思考,那个方案根本就行不通!spa
再后来,我又开始思考短语注音问题,短语注音问题的难点在于短语中的多音字,若是一个短语有多个多音字,这个短语全部可能的注音数量是指数的!若是咱们只想从汉字短语获得它的全部可能注音,那这根本就不是问题!短语注音问题是:.net
给定一个汉字短语集合,以及每一个汉字的全部发音(多是多个,若是算上模糊音,就更多了)code
要求:从该短语集合与汉字注音生成一个数据结构,该数据结构能够实现如下功能:
给定一串拼音,以最快的速度,找到这串拼音对应的短语。
这个问题一开始遇到的时候,以为很困难,也就一直没有太上心,由于这是个Map问题,那个时候在个人大脑中,只有 DAWG 能实现基于 DFA 的 Map,而我知道 DAWG 根本没法解决这种指数问题。
再到后来,偶然一个机会,我也不记得具体的动机是什么,我为 DFA 增长了一个接口:
int match_key(char delim, string text, function<void(int keylen, string value)> on_match);
delim 通常是 \t ,建立用于该接口的 DFA 时,输入是一行行的 (key, value) 文本: key \t value
match_key 碰到 \t 时,将已匹配的字符串长度做为 keylen , \t 后面的部分做为 value,经过 on_match 回调返回给调用方,之全部用回调,是由于在 ADFA 中,同一个 key 对应多个 value 是一种很天然的事情,而这多个 value 可能很是多。总之,从用户来看,这是一个很是简单有效的接口。而且,自动机的建立是一个分离的通用的程序(adfa_build)。这就造成了一个最简单的生态:adfa_build 从文本文件生成 DFA 二进制文件,在线服务器程序加载 DFA 二进制文件并调用 match_key 。 不须要为每个不一样的服务器程序专门写一个 addfa_build !
而后,我很快就意识到,这能够解决注音问题,关键是生成那个 DFA!最简单的办法是从短语集合生成一个个 (pinyin, 汉字) 的 (key, value) pair,这里 key 是拼音,汉字是 value,若是一个短语有多音字,就生成多个 (key, value) pair,先无论对应同一个 value 的 key 数目可能由于多音字从而是指数个。只傻乎乎地将这些 (key, value) pair 输出给 adfa_build 程序,最终确定能生成那个 DFA,并且是最小化的 DFA,由于该 DFA 建立过程是 Onfly Minimize 的,内存用量不会超爆。可是,可是——内存是不会爆,时间却仍然是指数级的!
这个问题曾经困扰了我好久,那段时间,我日思夜想,就是没法解决指数问题!后来终于有一天,洗澡的时候,我突然意识到,用 NFA 做为媒介!由于我很早就实现了 Jan Daciuk 的 Onfly ADFA Minimization 算法,在 match_key 给我灵感以后,有一天突发奇想,结合 match_key 的 delim,对 Daciuk 的算法作了一个理论上的泛化: add_adfa_tail,这个 adfa_tail 能够拥有任何复杂的 DAG 结构,若是把那多个可能的注音放到这个 adfa_tail 中,问题就解决了一半,剩下的一半,就是 DFA 的翻转,很简单的事情!
………………
…………
……
再接下来,灵感继续光临,多正则表达式匹配,只须要在每一个正则表达式以后,附加一个 delim+ID,一大半问题就解决了,剩下的一小半,就是纯粹的工程技术问题了
再后来,就是一些优化和泛化问题了,到目前为止,个人 DFA 多正则匹配算法还能够获取一类正则表达式的 submatch……