多正則表達式匹配(Multiple Regular Expression Matching)

目前 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……


欲知更多請參考: 多正則表達式匹配工具 的用法
相關文章
相關標籤/搜索