日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

nfa状态转换图正规式_0x02 从NFA到DFA

發布時間:2025/3/11 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nfa状态转换图正规式_0x02 从NFA到DFA 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

書接上文,上回說道NFA已經可以完全描述正則語言的全部內容。那么,我們在這一章探索一下一個比較復雜的正則表達式在用NFA做匹配的時候會有什么“不足“。

NFA匹配的"不足"

為了言之有物,不妨設要討論的模式為d?(c(a|b)*)*(b|c+)

圖1-1

效率

從上圖可以明確的看到存在大量的?轉換。這些?轉換在程序實現的時候就對應了大量的回溯入口,即決策點。那么很顯然,這個時候一定存在大量的遞歸回溯調用,自然也就必然會需要

大量時間來執行。

?轉換冗余

究其原因,無非就是冗余狀態太多了

冗余 ≠ 無用

這些看似冗余的轉換實際上對分組捕獲非常有用,因為在分組捕獲時,這些回溯可以記錄當前匹配的狀態還有剩余輸入信息等。但是,如果我們不用分組捕獲,只是要求模式全稱匹配,則這些轉換就是冗余的,我們需要通過狀態壓縮來實現確定化以避免任何回溯。

狀態壓縮

從上可知,若要完成狀態壓縮,則必須消除這些?轉換。但是,如何完成這一算法呢?完成后的確定化的結果仍然自動機么?當然是,并且它有個與NFA對應的名字叫做DFA。

DFA登場

DFA與NFA的區別

從圖1-1與圖1-2中可以明顯的發現NFA和DFA在轉換邊上的差異,歸納為下表。

NFADFA
?轉換存在不存在
相同輸入,不同轉換存在不存在

?轉換

closure---克林閉包

消除?轉換

function cleenClosure(){// BFSlet espilonSet = [state];let queue = [state];while(queue.length > 0){let q = queue.shift();for(const st of q.epsilonTransitions){if(espilonSet.findIndex(val => st.label === val.label) === -1){queue.push(st);espilonSet.push(st)if(st.isEnd) state.isEnd = st.isEnd}}}return espilonSet; }

Subset-Construction(子集構造)

借助上文的消除?轉換函數,我們可以將能夠通過?轉換到達的相連節點劃分為新DFA的等價狀態。

function toDFA(exp) {// 輸入字符集let aplhabets = new Set();// 原始正則表達式for(const ch of exp){if(ch !== "(" && ch !== "." && ch !== "?" && ch !== ")" && ch !== "*" && ch !== "|") {aplhabets.add(ch)}}const transExp = insertExplicitConcatOperator(exp);// 經過后綴改寫的正則表達式,后綴改寫目的在于解決運算符的優先級確定const postfixExp = toPostfix(transExp);let nfa = toNFA(postfixExp);//1. 從初始狀態開始,進行下一狀態等價集合的構造let q0 = createDFAState(false);q0.nfaStateSet = epsilonCleen(nfa.start);q0.isEnd = nfa.start.isEnd;//2. 存儲新發現等價狀態的工作集let workLst = new Array();//3. 存儲已經生成等價狀態的集合let dfaStates = [q0];workLst.push(q0);//4. 不停增加和刪除等價狀態,知道workLst變為空集while(workLst.length > 0){let q = workLst.shift();for(const ch of aplhabets) {// 4.1 計算delta并合并進入新狀態t = epsilonCleenDelta(q,ch);if(t != null) {if(!dfaStatesHas(dfaStates,t)){dfaStates.push(t);workLst.push(t);q.transitions[ch] = t} else {let node = dfaStatesFind(dfaStates,t);node.isEnd = t.isEnd;q.transitions[ch] = node;}}}}return q0; }

圖1-2

總結

以上是生活随笔為你收集整理的nfa状态转换图正规式_0x02 从NFA到DFA的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。