[英]converting CFG to regular expression
這是一個 CFG,它生成 0、1 或 0 和 1 這樣排列的字符串(001, 011)
,其中一個字符的計數必須大於另一個,例如00011111
或00000111
。
S → 0S1 | 0A | 0 | 1B | 1
A → 0A | 0
B → 1B | 1
我嘗試使用本指南將其轉換為正則表達式,但我被0S1
,因為我在轉換0S1
遇到了麻煩,因為在該指南中找不到與它類似的任何內容。
S → 0S1 | 0+ | 0 | 1+ | 1
A → 0A | 0 = 0+
B → 1B | 1 = 1+
我之前的嘗試之一是0+0+1|0+1+1|1+|0+
但它不接受我上面提到的字符串,如00011111
和00000111
。
^(?!01$)(?!0011$)(?!000111$)(?!00001111$)(?=[01]{1,8}$)0*1*$
您無法將其完美地轉換為正則表達式,但您可以通過確保輸入的0
和1
數量不同來接近。 這最多匹配 8 位數字。
^
首先你從一行的開頭開始(?!01$)
確保字符不是01
(?!0011$)
確保字符不是0011
000111
和00001111
相同1
到8
零和一個(這是必需的,以確保輸入不是由更多數字組成,如000000111111
,因為它們的對稱性未經驗證)^(?!01$)(?!0011$)(?!000111$)(?!00001111$)(?!0000011111$)(?=[01]{1,10}$)0*1*$
(通過再添加一個對稱驗證,你跳了 2) A
和B
很簡單,正如您看到的0+
和1+
。 S
中第一個之后的連接也很容易: 00+
, 0
, 11+
, 1
,所有這些都混合成一個導致(0+|1+)
。 問題在於第一個連接0S1
。
所以問題可以縮短為S = 0S1
。 這個語法是遞歸的。 但既不是left linear
也不是right linear
。 要識別此語法的輸入,您需要“記住”您找到了多少個0
,以便能夠匹配相同數量的1
,但從正則語法(通常和正則表達式)創建的有限狀態機) 沒有計算歷史。 它們只是狀態和轉換,機器從一種狀態“跳躍”到另一種狀態,並且不記得在轉換中經過的“路徑”。
出於這個原因,您需要更強大的機器(如下推自動機),可以從上下文無關的語法(如您的)構建。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.