回覆列表
  • 1 # mtoug3225

      正則表示式轉換NFA演算法  基礎的正則表示式:  對於正則表示式應用運算子部分構造方法:  

    1.符號棧,即運算的符號,其儲存的為wchar_t型別,為連線,左括號,選擇3種運算子。  

    2.NFA棧,即儲存的NFA,這裡因為整個計算過程都是更新一個Graph結構,所以這裡的NFA棧保留的其實是當前NFA的開始和結束資訊,即start和end。  

    3.具體的主要演算法執行流程:  1.遍歷輸入的正則表示式,這裡正則表示式的儲存在CString變數中,可以透過下標訪問;  2.首先初始化一張儲存NFA的Graph結構,演算法過程中的節點的數量不會超過正則表示式長度的2倍,所以這裡直接開闢一個大小為正則表示式長度為2倍的Graph結構;  3.遇到非運算子,及正則表示式裡面的轉移符號的時候,這裡就需要構造一個基本的NFA,一個初始狀態,一個終止狀態,然後由初始狀態至終止狀態有一條為該轉移符號的邊,此時仍然需要檢查正則表示式的下一個符號,如果不是運算子或者為左括號,此時應該運算棧中新增一個連線運算子,然後將構造的基本NFA新增入NFA棧中,方便以後將基本的NFA進行其他選擇,重複,連線運算;  

    4.遇到非運算子時,需要分一下四種運算子的情況;  

    5.如果是運算子“)”,即右括號,此符號屬於運算級最高的符號了,所以它要在符號棧中彈出所有符號運算,直到遇到“)”匹配,運算過程中根據符號棧中彈出的符號計算;  

    6.如果是運算子“(”,即左括號,此符號只是用來和右括號結合的,所以直接將該運算子壓入符號棧中即可;  

    7.如果是運算子“*”,即重複符號,這個在正則表示式中運算級最高,直接進行計算,計算方法就是從NFA棧中彈出一張圖,然後得到兩個未分配的新節點,新增4條上面圖表示的那樣的邊,然後重新設定NFA的start和end之後將新的NFA壓入NFA棧中即可,運算後檢查其後跟隨的元素,如果是轉移符號或者左括號,則必須要向符號棧中新增連線符號;  

    8.如果是運算子“+”,即選擇符號,由於此符號的優先順序沒有連線符號高,所以此時應該彈出符號棧中優先順序高於它的符號,但是“(”不參與彈出,所以這裡只是彈出連線符號和自身“+”符號運算,然後將該符號壓入符號棧等候計算;  

    9.正則表示式遍歷完畢之後,需要彈出所有的符號棧進行計算,最後NFA棧中的唯一NFA就是所求的NFA;  接下來就是具體的運算的演算法,這裡點與點的連線透過更新Graph中相應的點的鄰接連結串列即可;  

    10.連線運算,此時需要彈出NFA棧中的兩個NFA,然後將其中一個的end連線至另一個的start,然後更新新的NFA的start和end,壓入NFA棧中。  

    11.選擇運算,此時需要彈出NFA棧中的兩個NFA,然後Graph重新分配兩個節點,作為新的NFA的start和end,然後新的start分別連線彈出的兩個NFA的start,彈出的兩個NFA的end分別連線新的end即構成新的NFA,壓入NFA棧中。  

    12.閉包運算,此時需要彈出NFA棧中的一個NFA,然後Graph重新分配兩個節點,作為新的NFA的start和end,然後新的start連線彈出NFA的start,彈出NFA的end連線新的end,然後新增一條新的start到新的end的一條空邊和一條舊的end到舊的start的一條空邊,將新的NFA壓入NFA棧中。  最終的執行Graph的結果輸出樣式:  NFA的顯示是根據上面演算法生成的Graph的結構進行顯示結果:  

  • 中秋節和大豐收的關聯?
  • 章父否認奶茶妹妹章澤天離婚,你怎麼看?