nfa 和 dfa**—要深入了解正規表示式,必須首先理解有窮自動機
。
有窮自動機(finite automate)是用來模擬實物系統的數學模型,它包括如下五個部分:
下圖為一台有窮自動機
可以看到,該自動機包含四個狀態(有限狀態)q0, q1, q2, q3,兩個輸入字元a, b,轉移函式如圖所示,起始狀態為q0,接受狀態為q3。
有窮自動機,按照轉移函式的不同,又可分為確定型有窮自動機(determinism finite automate, dfa)
,與非確定型有窮自動機(non-determinism finite automate, nfa)
。
非確定有窮自動機容許轉移函式不確定,換句話說,對任意狀態,輸入任意乙個字元,可以轉移到0個,1個或者多個狀態。
下圖是一台非確定有窮自動機,可以看到,對狀態q0輸入字元a,既可以轉移到q0,也可以轉移到q1,這就是「非確定」的意義所在。
對某個自動機來說,如果從起始狀態,接受一系列輸入字元,可以轉移到接受狀態,即認為這一系列字元可以被自動機接受。
如果兩台自動機能夠接受的輸入字串(或者叫做「正則語言」regular language)完全相同,則這兩台自動機是等價的。可以證明,對於每乙個非確定有窮自動機,都存在與之等價的確定型有窮自動機(證明略)。
正規表示式就是建立在自動機的理論基礎上的:使用者寫完正規表示式之後,正則引擎會按照這個表示式構建相應的自動機(可能是nfa,也可能是dfa,但它們必定是等價的),若輸入一串文字之後,自動機抵達了接受狀態,則這串文字可以「匹配」使用者指定的正規表示式。
下面是同乙個正規表示式 a|ab 對應的nfa和dfa
在mastering regular expression中,friedl首先分析了nfa和dfa的區別,dfa比較快,但不提供backtrack(回溯)功能,nfa比較慢,但提供了backtrack功能。
在分析兩種引擎的匹配過程時,friedl指出,nfa是基於表示式的(regex-directed),而dfa是基於文字的(text-directed)。
舉例來說,對於正規表示式 to(nite|knight|night),nfa在匹配最開始兩個字元(to)之後,剩下的三個元件(component)是 nite, knight 和 night,於是正則引擎會依次嘗試這三個選擇分支(每次嘗試乙個);而dfa在匹配最開始兩個字元之後,會將剩下的三個選擇拆分作字元,並行嘗試,也就是說,匹配 to 之後,先匹配 k 或者 n ,如果 k 不能匹配,則放棄 knigth 所在的分支,再匹配 i ,再匹配 t 或 g ……這樣繼續下去,直到匹配結束。
不幸的是,friedl對匹配過程的分析,是完全錯誤的——引擎的不同,是指構建的自動機的不同,而不是匹配演算法的不同!
dfa引擎在任意時刻必定處於某個確定的狀態,而nfa引擎可能處於一組狀態之中的任何乙個,所以,nfa引擎必須記錄所有的可能路徑(trace multiple possible routes through the nfa),nfa之所以能夠提供backtrack的功能,原因就在這裡。
傳統的nfa匹配演算法是帶回溯的深度優先搜尋(backtracking depth-first search,就是上文所說的regex-based過程),而新的pcre演算法提供了效率更高的廣度優先搜尋,可以同時保持所有可能的nfa狀態(請參考尤其是lecture notes的section 2.2)。
friedl的錯誤就在這裡,他混淆了應用pcre演算法的nfa與dfa的匹配過程。需 要指出的是,即使應用pcre演算法,nfa的速度仍然低於dfa,這是由nfa需要同時儲存多種可能的性質決定的。從理論上說,如果我們不需要應用 backtrack,完全可以從nfa構造出等價的dfa,再進行匹配,這樣能大大提高速度——代價是,dfa需要更多的空間。
有限狀態自動機 正規表示式
將nfa轉化為dfa nfa和dfa的效率 記號有字母表中的符號組成的有限長度的序列。記號s的長度記為 s 長度為0的記號稱為空記號,記為 有限自動機 finite state automaton 為研究某種計算過程而抽象出的計算模型。擁有有限個狀態,根據不同的輸入每個狀態可以遷移到其他的狀態。非確...
編譯原理第三章 有窮自動機與正規表示式理論基礎
3.3 面對眾多的源語言的詞法分析處理,總體上,超前讀入和某種假讀處理是 b a 可以避免的 b 不可避免的 c 徒勞無益的 3.4 下述正規表示式中 d 與 0 1 等價 a 0 1 b 0 1 c 0 1 d 0 1 0 1 3.6 不以0開頭的十進位制無符號整數 的正規式為 c a 12345...
Unit 3 詞法分析 從正規表示式到有窮自動機
引言 正規表示式有兩種基本要素 字元表示式和 表示式,以及三種基本運算 並 連線和閉包 正規表示式並不能直接用來解析字串,所以引入有窮自動機這種適合轉化為電腦程式的模型 其特點是從每乙個狀態只能發出一條具有某個符號的邊。也就是說不能出現同乙個符號出現在同一狀態發出的兩條邊上。允許從乙個狀態發出多條具...