Regex轉NFA

來源:互聯網
上載者:User
文章目錄
  • 資料結構描述
  • Regex轉換NFA演算法
  • NFA的顯示

    最近一直在忙著寫大作業,考試複習,複習演算法的時候寫了一些隨筆,現在忙起來都落下了部落格,這裡有一個VC++寫的大作業,主要是Regex轉NFA並顯示。內容如下。

資料結構描述

介紹一下NFA在表示的結構設計,由於NFA本身是一種有向圖,所以這裡的儲存結構設計和鄰接表相似,圖中的每個節點後面是一些與其串連的節點的值,具體設計4.1。

 

圖4.1

a)         Graph由若干個GraphLine組成,其中start和end標識了NFA的初始狀態和終止狀態的下標;

b)         GraphLine的由一個節點和以該節點為起點所指向的節點群組成,而所指向的節點利用EdgeLink表示,其中有指向邊上的轉移字元和指向的節點群組成;

c)         GraphNode表示圖的基本組成節點,其中節點有唯一的ID和位置;

Regex轉換NFA演算法

基礎的Regex,4.2所示

 

圖4.2

對於Regex應用運算子部分構造方法4.3

 

圖4.3

  1.     符號棧,即運算的符號,其儲存的為wchar_t類型,為串連,左括弧,選擇3種運算子。
  2.     NFA,即儲存的NFA,這裡因為整個計算過程都是更新一個Graph結構,所以這裡的NFA棧保留的其實是當前NFA的開始和結束資訊,即start和end。

具體的主要演算法執行流程:

  1.     遍曆輸入的Regex,這裡Regex的儲存在CString變數中,可以通過下標訪問
  2.     首先初始化一張儲存NFA的Graph結構,演算法過程中的節點的數量不會超過Regex長度的2倍,所以這裡直接開闢一個大小為Regex長度為2倍的Graph結構
  3.     遇到非運算子,及Regex裡面的轉移符號的時候,這裡就需要構造一個基本的NFA, 一個初始狀態,一個終止狀態,然後由初始狀態至終止狀態有一條為該轉移符號的邊,此時仍然需要檢查Regex的下一個符號,如果不是運算子或者為左括弧,此時應該運算棧中添加一個串連運算子,然後將構造的基本NFA添加入NFA棧中,方便以後將基本的NFA進行其他選擇,重複,串連運算
  4.     遇到非運算子時,需要分一下四種運算子的情況
    1.     如果是運算子“)”,即右括弧,此符號屬於運算級最高的符號了,所以它要在符號棧中彈出所有符號運算,直到遇到“)”匹配,運算過程中根據符號棧中彈出的符號計算
    2.     如果是運算子“(”,即左括弧,此符號只是用來和右括弧結合的,所以直接將該運算子壓入符號棧中即可
    3.     如果是運算子“*”,即重複符號,這個在Regex中運算級最高,直接進行計算,計算方法就是從NFA棧中彈出一張圖,然後得到兩個未分配的新節點,添加4條上面圖表示的那樣的邊,然後重新設定NFA的start和end之後將新的NFA壓入NFA棧中即可,運算後檢查其後跟隨的元素,如果是轉移符號或者左括弧,則必須要向符號棧中添加串連符號
    4.     如果是運算子“+”,即選擇符號,由於此符號的優先順序沒有串連符號高,所以此時應該彈出符號棧中優先順序高於它的符號,但是“(”不參與彈出,所以這裡只是彈出串連符號和自身“+”符號運算,然後將該符號壓入符號棧等候計算
  5.     Regex遍曆完畢之後,需要彈出所有的符號棧進行計算,最後NFA棧中的唯一NFA就是所求的NFA

接下來就是具體的運算的演算法,這裡點與點的串連通過更新Graph中相應的點的鄰接鏈表即可

  1.     串連運算,此時需要彈出NFA棧中的兩個NFA,然後將其中一個的end串連至另一個的start,然後更新新的NFA的start和end,壓入NFA棧中。
  2.     選擇運算,此時需要彈出NFA棧中的兩個NFA,然後Graph重新分配兩個節點,作為新的NFA的start和end,然後新的start分別串連彈出的兩個NFA的start,彈出的兩個NFA的end分別串連新的end即構成新的NFA,壓入NFA棧中。
  3.     閉包運算,此時需要彈出NFA棧中的一個NFA,然後Graph重新分配兩個節點,作為新的NFA的start和end,然後新的start串連彈出NFA的start,彈出NFA的end串連新的end,然後添加一條新的start到新的end的一條空邊和一條舊的end到舊的start的一條空邊,將新的NFA壓入NFA棧中。

最終的運行Graph的結果輸出樣式4.4

 

圖4.4

NFA的顯示

NFA的顯示是根據上面演算法產生的Graph的結構進行顯示顯示結果4.5

 

 

具體的顯示方法是從Graph的start節點開始調用繪製函數,該繪製函數的功能是首先檢查該節點是否繪製,如果未繪製則進行繪製,如果已經繪製則不進行繪製,然後根據自己的位置確定他鄰接點的位置,然後繪製至其他點的邊,然後遞迴的調用其鄰接點,函數的結束條件是繪製到end或者其鄰接點已經繪製。

這裡對代碼類和函數的作用進行主要的說明,代碼的實現細節可以參看代碼中的注釋

代碼主要類別檢視5.1

 

圖5.1

CInputExpDlg

Regex輸入對話方塊

GraphNode

 

EdgeLink

 

GraphLine

 

Graph

 

TranslateModel

 

原始碼:http://files.cnblogs.com/weixliu/RextoNFA.rar

轉載請註明出處,謝謝,

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.