8.3 回溯

比起DFA汗贫,NFA看起來足夠“麻煩”:它的狀態(tài)是不確定的,這有點像走迷宮耿战,越走岔路口越多蛋叼,最后不會迷路嗎?

不過剂陡,NFA的正則引擎自有辦法:如果有多個可能的狀態(tài)狈涮,它們會在選擇時記錄下這些狀態(tài)備用,然后才選擇其中某個狀態(tài)嘗試鸭栖;如果之后遇到死路歌馍,則退回去,選擇最近一次記錄的且未嘗試過的狀態(tài)晕鹊;如果又遇到死路松却,再選擇最近一次記錄的且未嘗試過的狀態(tài)...

這有點像在分岔路口留下標記——如果我們在遇到的每個分岔路口都留下標記暴浦,即使前頭是死路,也可以根據(jù)標記返回晓锻,而不會迷路歌焦。

為了說明NFA的匹配過程,來看看第2章舉過的雙引號字符串匹配的例子砚哆,所用的正則表達式為".*",字符串為"quoted string"独撇,匹配過程如圖所示:

[圖片上傳失敗...(image-f3c454-1545311212332)]

從圖中可以看出,在匹配的過程中躁锁,.*曾經(jīng)匹配了quoted string"纷铣,但是為了表達式中最后一個"的匹配,.*不得不“交還”最后的"灿里,這種“嘗試失敗-重新選擇”的過程关炼,就是回溯(backtracking)。

回溯只屬于NFA引擎匣吊。從之前地原理圖中可以看到,NFA匹配時寸潦,正則引擎并不準確知道當前的狀態(tài)色鸳,只能在所有狀態(tài)不確定的地方將各種狀態(tài)都保存下載(現(xiàn)在已經(jīng)匹配了哪些字符,進行到字符串中的哪個位置见转,正則表達式中的哪個位置)命雀,逐一嘗試,發(fā)現(xiàn)此路不通斩箫,則退回來吏砂,選擇最近保存的其臺狀態(tài)嘗試...如此進行下去,直到達到最終狀態(tài)乘客;或者所有可能狀態(tài)都嘗試完畢狐血,仍不能達到最終狀態(tài)。

看到這里就不難明白為什么不推薦使用.*了易核,因為.幾乎能匹配任何字符串匈织,而*又表示“匹配優(yōu)先”,所以正則引擎再處理.*后的其他元素之前牡直,會讓.*“吞掉”幾乎整個字符串缀匕。仍然是上面的正則表達式,只是字符串變?yōu)?code>"quoted" string碰逸,回溯的次數(shù)大大增加了乡小,如果在結尾的"之后還有很長的文本,則回溯的次數(shù)還可能大大增加饵史,匹配過程如圖所示:

[圖片上傳失敗...(image-2e92e0-1545311212332)]

為避免這類問題满钟,最好的辦法是準確表達意圖胜榔,比如規(guī)定雙引號字符串內部不允許出現(xiàn)雙引號字符,就要將表達式改為"[^"]*"零远;當然也可以換用忽略優(yōu)先量詞苗分,將表達式改為".?*"。不過總的經(jīng)驗是牵辣,除非確實必要摔癣,否則盡量不要使用.*

要注意的不僅僅有.*纬向,還有更糟的情況择浊,比如(...*)*之類的表達式,這時候回溯的次數(shù)會呈指數(shù)級增長逾条,卻不會對匹配有任何影響琢岩,所以絕對應該避免。

在實際引用中师脂,不僅要注意自己寫的正則表達式担孔,還要防范外界對惡意程序,它們刻意使用會造成大量回溯的表達式吃警,將計算機的資源消耗殆盡糕篇,這種攻擊有一個專門的名詞,叫做正則表達式拒絕服務攻擊(regular expression denial of service)酌心。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末拌消,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子安券,更是在濱河造成了極大的恐慌墩崩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侯勉,死亡現(xiàn)場離奇詭異鹦筹,居然都是意外死亡,警方通過查閱死者的電腦和手機壳鹤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門盛龄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芳誓,你說我怎么就攤上這事余舶。” “怎么了锹淌?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵匿值,是天一觀的道長。 經(jīng)常有香客問我赂摆,道長挟憔,這世上最難降的妖魔是什么钟些? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮绊谭,結果婚禮上政恍,老公的妹妹穿的比我還像新娘。我一直安慰自己达传,他們只是感情好篙耗,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宪赶,像睡著了一般宗弯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搂妻,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天蒙保,我揣著相機與錄音,去河邊找鬼欲主。 笑死邓厕,一個胖子當著我的面吹牛,可吹牛的內容都是我干的扁瓢。 我是一名探鬼主播邑狸,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼涤妒!你這毒婦竟也來了?” 一聲冷哼從身側響起赚哗,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤她紫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屿储,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贿讹,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年够掠,在試婚紗的時候發(fā)現(xiàn)自己被綠了民褂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡疯潭,死狀恐怖赊堪,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情竖哩,我是刑警寧澤哭廉,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站相叁,受9級特大地震影響遵绰,放射性物質發(fā)生泄漏辽幌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一椿访、第九天 我趴在偏房一處隱蔽的房頂上張望乌企。 院中可真熱鬧,春花似錦成玫、人聲如沸加酵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虽画。三九已至,卻和暖如春荣病,著一層夾襖步出監(jiān)牢的瞬間码撰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工个盆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脖岛,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓颊亮,卻偏偏與公主長得像柴梆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子终惑,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內容