最近作了一項工做:容許一個 DFA 有多個起始狀態(能夠稱做根: root)。引入這個概念有不少好處,主要體如今 DFA Union 中,這個操做經過 NFA 到 DFA 的轉化來完成,算法思想很簡單:正則表達式
建立一個 NFA,該 NFA 只有初始狀態是非肯定 (non-DFA) 狀態:初始狀態只有 ε 轉移,這些 ε 轉移指向全部要被 Union 的 DFA 的初始狀態,而後將該 NFA 轉化爲 DFA。算法
由於 NFA 轉化 DFA 是 NSpace 的,雖然不少數狀況下只有線性複雜度,咱們仍然但願儘量減少這個複雜度。性能
在建立多正則表達式匹配的 DFA 的過程當中,就有一個 DFA 的 Union 操做,在這個過程當中,若是狀態膨脹失去控制,須要使用某種方式對正則表達式集合進行分組,以便抑制這種狀態膨脹。分組後會生成多個 DFA ,可是爲了應用程序接口方便統一,將這多個 DFA 揉進一個 DFA 對象,每一個分組的 DFA 就須要一個不一樣的初始狀態(根)。優化
雖然以前我也曾想過 DFA 包含多個初始狀態(根)的可能性,但一直沒有深刻思考,此次通過仔細思考,發現:對於(全部的) DFA 最小化算法,從理論上講,徹底沒有必要限制爲單根 DFA,無論有多少個根,算法都能正常工做!惟一須要注意的是,最小化先後的根,在某些應用中須要一一對應起來。ui
最小化以前的多根 DFA 能夠徹底是獨立的,惟一的要求是全部 DFA 的狀態 ID 屬於同一個 ID 空間,這很簡單,工程上用同一個 DFA 對象來表達便可,對於 分離的多個 DFA 對象,只須要實現一個 DFA 包裝器,將多個分離的 DFA 的狀態 ID 從新映射便可。spa
如此,就完成了執行多根 DFA 最小化的全部準備。最小化完成以後,這些多個 DFA 會共享一些相同的尾部,通常狀況下,頭部不會共享;不過極端狀況下,例如 DFA1 是 DFA2 的子集,那麼,從 DFA2 的根就能到達 DFA1 的根,此時整個 DFA1 就被徹底共享了。.net
全部的尾部都被最小化了,而後再用 NFA 轉化 DFA 的方式執行最小化,這樣,大大減少了 NFA 轉 DFA 的時間和內存消耗。對象
細節可參考:多正則表達式匹配 (Multiple Regular Expression Matching) 中的動態 DFA 算法blog
主要有兩點:在實現這個概念的過程當中,對個人 adfa_minimize 作了一些重構,同時也進行了一些優化。接口