reg = /^(0+|0*1((10*1)|(01*0))*10*)$/
其中
-
0+
表示字符串可以全為0 - 第一個
0*
表示字符串可以以0開頭 - 核心的句式是:
1((10*1)|(01*0))*10*)
原理如下:
一個二進制數后面加一個“0”相當于該數乘以2,一個二進制數后面加一個“1”相當于該數乘2加1。
設定三個狀態,分別叫做0、1和2,它們表示當前的數除以3所得的余數。有以下的幾種可能:
0@0 => 0 表示狀態0后面是0時,變成狀態0
0@1 => 0 表示狀態0后面是1時,變成狀態1
1@0 => 2 表示狀態1后面是0時,變成狀態2
1@1 => 0 表示狀態1后面是1時,變成狀態0
2@0 => 1 表示狀態2后面是0時,變成狀態1
2@1 => 2 表示狀態2后面是1時,變成狀態2
狀態0既是我們的初始狀態,也是我們的最終狀態。我們的自動機就做好了。現在,假如二進制數10010走進來了。從狀態0出發,機器首先讀到一個“1”,于是當前位置挪到狀態1,表明目前該數模3余1;然后,系統讀了一個“0”,我們緊跟著走到狀態2,表明二進制數“10”被3除余2;下一步,我們回到狀態1,表明“100”除以3余1;再往后,我們得知“1001”能被3整除。最后呢,我們讀到一個0,“1001”的兩倍當然還是能被3整除,我們依舊停留在原位。我們得到結論:二進制數10010能被3整除。
有限狀態自動機是可以轉化為正則表達式的。上面的這個自動機轉化起來非常容易。我們可以先試著用自然語言敘述一下。首先,每個二進制數第一位必然為“1”。到達狀態1后,我們可以隨意地、任意多次地在狀態1周圍繞圈圈,最終回到狀態1。臨近末尾,我們再讀到一個“1”返回狀態0,這之后隨便讀多少個“0”都可以了。現在問題分解為:我們又如何用正則表達式表述“從狀態1出發隨意地走最終回到狀態1”呢?在本例中,這是很好描述的:它可以是字符串“1000..001”和“0111..110”的任意組合。把這些東西用正則表達式寫出來,就是我們剛才那個神秘的式子:1((10*1)|(01*0))*10*
參考這里