《演算法》筆記 16 正規表示式

2021-10-19 12:00:37 字數 1609 閱讀 2315

除了查詢子字串,在很多時候並不知道被查詢模式的完整資訊,這時就需要用到正規表示式了。正規表示式在子字串查詢、合法性校驗、網路爬蟲等方面有著非常廣泛的應用。

正規表示式對模式的描述,基於幾個基本操作。

如何根據正規表示式所描述的模式來匹配文字呢?子字串查詢中使用的有序狀態自動機dfa會根據文字中的字元改變自身的狀態,但正規表示式匹配比子字串查詢更複雜。因為或操作的存在,自動機無法僅根據乙個字元就判斷出模式是否出現;再加上閉包的存在,自動機甚至無法知道需要檢查多少字元才會匹配失敗。為了克服這些困難,需要非確定有限狀態自動機nfa。

根據kleene定理,任意正規表示式都存在乙個與之對應的非確定有限狀態自動機,反之亦然。所以任意正規表示式都可以轉換為乙個非確定有限狀態自動機,然後就可以模式nfa的執行軌跡來進行匹配了。

正規表示式((a*b|ac)d)所對應的nfa如下圖:

nfa具有以下特點:

這裡約定將所有的模式都包含在括號中,一次nfa中的第乙個狀態和最後乙個狀態都對應的是括號。

在檢查文字與模式是否匹配時,nfa需要不斷讀取文字,直到nfa變為接受狀態,或到達文字末尾。由於或操作和閉包操作的存在,nfa從乙個狀態轉換到了乙個狀態的規則與dfa有所不同,在nfa中有兩種轉換方式:

比如在上圖的nfa中,由2->3, 1->6等都是ε轉換,ε轉換說明很多時候,nfa從乙個狀態轉換到的下乙個狀態是不確定的,比如從狀態3即可以到狀態4,也可以回到狀態2。正是由於這種不確定性的存在,nfa執行時,需要系統地嘗試過所有的可能性後,才能得知是否匹配成功。

使用nfa進行正規表示式匹配的過程與使用dfa進行子字串查詢的整體過程大致相同,也是先根據給定的正規表示式構造nfa,然後模擬nfa在給定文字上的執行軌跡。

nfa的表示

首先考慮的是該如何表示nfa。正規表示式本身已經給出了所有的狀態名,如果正規表示式的長度為m,那麼0到m之間的整數就是所有的狀態名,於是用char陣列re儲存正規表示式的每個字元,對於匹配轉換,如果re[i]存在於字母表中,那麼就存在乙個從i到i+1的匹配轉換。

對於ε轉換,用有向圖表示,它們都是連線0到m之間各個頂點的有向邊。

構造與正規表示式相對應的nfa

在表示nfa的時候會使用乙個char陣列,乙個有向圖,另外還有乙個棧來記錄所有左括號和或操作符的位置。

public class regular  else

lp = or;

}if (i < m - 1 && re[i + 1] == '*')

if (re[i] == '(' || re[i] == '*' || re[i] == ')')

g.addedge(i, i + 1);}}

}

nfa的模擬與可達性
public boolean recognize(string txt) 

for (int i = 0; i < txt.length(); i++)

for (int v : pc)

if (v == m)

return true;

return false;

}

《演算法》筆記 16 正規表示式

除了查詢子字串,在很多時候並不知道被查詢模式的完整資訊,這時就需要用到正規表示式了。正規表示式在子字串查詢 合法性校驗 網路爬蟲等方面有著非常廣泛的應用。正規表示式對模式的描述,基於幾個基本操作。如何根據正規表示式所描述的模式來匹配文字呢?子字串查詢中使用的有序狀態自動機dfa會根據文字中的字元改變...

正規表示式 正規表示式函式 筆記

筆記直接使用pycharm製作,需要原始檔請私聊。正規表示式函式 1.match 2.search 3.全域性匹配函式 全域性匹配 re.compile 正規表示式 findall 資料 import re string poythonydasadcasa pat2 p.y 懶惰模式執行 較精準 r...

正規表示式筆記

不同的語系編碼的順序不一樣 lang c 0 1 2 3 a b c d z a b c d z lang zh cn 0 1 2 3 4 a a b b c c z z 使用正規表示式時,需要留意環境的語系是什麼,否則會有不同的結果 alnum 英文大小寫字元及數字 0 9 a z a z alp...