自己實現一個 DFA 串模式識別器(一)

發表於2020-04-18

自己實現一個 DFA 串模式識別器

前言

 這是我編譯原理課程的實驗。希望讀完這篇文章的人即便不知道 NFA,DFA 和正規表示式是什麼,也能夠對它們有一個簡單的理解,並能自己去實現一個能夠識別特定模式的串模式識別器。它可能會像是這樣:

  1. 輸入一個正規表示式:(s.f.l*.e)|(a*.b*)

  2. 輸入:“sfe”

    輸出:matched!

    輸入:“sflea”

    輸出:failed!

注:'.' (點字元)表示連線運算

​  文章分為兩部分,理論背景:介紹相關概念和原理;程式實現:使用 C++ 實現一個 DFA 串模式識別器。

理論背景

引入

​  我比較喜歡將任何理論和技術從自己能應用和理解的最低點開始闡述,因為這樣往往可以將新的知識與過往的知識體系相聯結。同時在一定的場景下思考它如何被應用,以切實的實現將所學流暢的抵達所用。這篇文章亦是如此。

​  首先我們要處理一個簡單的問題,給出如下串:

​  例一:

ab,abab,ababab,abababab,...

a,aa,aaa,aaaa,...

aab,aabaab,aabaabaab,...

​  對於第一行給出的這些字串,請問你是否能夠編寫簡單程式,識別出給定的一個字串 S 是否屬於第一行中的某一個字串?如 ab 屬於第一行,abab 屬於第一行,但 aab 不屬於。我相信有過一定程式設計經驗的人都可以通過簡單的分支-迴圈邏輯,或者是一些字串演算法來寫出一個判別程式。對於第二、三行也是如此。因為我們發現它們都具有一定的規律性,或者也可以稱為遵循一定的模式。當情況很簡單時我們並不用思考太多,只是不斷的複雜化、堆疊我們的邏輯程式碼,希望程式碼邏輯能夠捕獲特定模式下所有的串。不過有時情況會很複雜,以至於我們非常困難去設計一個邏輯來實現判別(捕獲模式)。比如下面這個串:

​  例二:

abb,aabb,babb,ababb,aaaaaaabb,bbbbbbbbabb,aababbababbbabbabb,

ababababaaaaaaabbbbbbbaaaaaaabbbbbaababbbabababbabbbbaabb,...

​  你可能會覺得這些串完全沒有任何邏輯和規律可言嘛!沒錯,單憑對已給出的這些串很難發現規律。但是它確實有自己的模式,而且我可以提前告訴你,它們是由我根據正則(規)表示式:(a|b)*abb 產生的。如果你沒有了解過正則(規)表示式也不必擔心,先跳過它。

注:在某些不嚴格情況下,不區分正規表示式正規表示式

模式串和正規表示式

​  在前文中,我重複了很多次模式這個詞。其實我們之前看到的每一組串都是遵循特定的模式。非正式的,我們可以說 一組字串構成的集合由一個與該組相關的稱為模式的規則來描述。並且這個模式被說成匹配該集合中的每個字串。

注:這裡的模式特指 串的模式

​  可以 以例一為例介紹模式。非正式的表示:

例一的第一行的模式為:由 a、b 交替出現組成的串

第二行模式為:由若干個 a 組成的串

第三行模式為:由若干個 abb 組成的串

​  我們可以用自然語言描述簡單的模式,但是無法去描述複雜的模式。所以就需要一種形式化的表示方法,來幫助我們表達。這就是正規表示式。正規表示式是表示模式的一種重要方法。每個模式匹配一個字串集。簡單來說,正規表示式需要一個字母表,其中字母表上的字串是該字母表中符號的有窮序列。和定義在其上的一些運算。通過歸納已有的模式串,我們可以提出以下幾種運算:

連線運算:以英文 '.' 表示。如:a.b 表示 串 ab

或運算:以英文 '|' 表示。如:a|b 表示串 a 或串 b

克林閉包運算:以英文 '*' 表示。如:a* 表示串:\(\epsilon\) ,a,aa,aaa,...

注:1. \(\epsilon\) 表示空串 2. 為了我的程式方便處理,我將連線運算設定成了 英文的點。

​  需要注意的是,運算並不止上述三種,但是我們主要討論他們,並且很多運算可以通過它們複合得到。如:

正閉包:以英文:'+' 表示,當字母表只有 a 時 a+ 等價於 a.a*

? 運算:以英文:'?' 表示,當字母表只有 a 時 a? 等價於 (a|\(\epsilon\))

指數運算等

​  現在我們將例二中的正規表示式重新書寫為:(a|b)*a.b.b 。參照上述運算的含義,我想你應該可以理解這個模式所代表的串的集合會是什麼樣的。

​  注意,正規表示式所能描述的模式是有限的。它只能表示固定次數的重複或給定結構沒有指定次數的重複。它不能用於描述均衡或者巢狀結構。如具有括號配對的符號串集合正規文法無法描述,但是可以通過更復雜的上下文無關文法來描述。關於文法不作多描述。

參考資料:https://book.douban.com/subject/2970069/

出於篇幅考慮和更好的閱讀體驗,本文將分成三個部分,歡迎繼續閱讀餘下篇章。下一篇內容是正規表示式的實現原理,涉及 NFA、DFA 的概念和相關演算法。




作者:Skipper
出處:https://www.cnblogs.com/backwords/p/12726258.html
本部落格中未標明轉載的文章歸作者 Skipper 和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

相關文章