回溯法(三)——正則表示式匹配問題
阿新 • • 發佈:2020-08-12
- 遇到特殊字元的時候,我們就有多種處理方式了,也就是所謂的岔路口:
- “*”有多種匹配方案,可以匹配任意個文字串中的字元,我們就先隨意的選擇一種匹配方案,然後繼續考察剩下的字元。如果中途發現無法繼續匹配下去了,我們就回到這個岔路口,重新選擇一種匹配方案,然後再繼續匹配剩下的字元。
- "?"有兩種匹配方案,匹配0個或者1個:我們就先選擇匹配0個的方案,然後繼續考察剩下的字元。如果中途發現無法繼續匹配下去了,我們就回到這個岔路口,重新選擇匹配1個的方案,然後再繼續匹配剩下的字元。
- 遇到非萬用字元時,我們就直接跟文字的字元進行匹配,如果相同,則繼續往下處理;如果不同,則回溯(即當前一段程式結束,回到上一個呼叫的程式入口)。
C++版本程式碼如下
#include<iostream> #include<string> #include <limits> using namespace std; bool matched = false; void match(int ti, int pj, char text[], int tlen, char patten[], int plen){ // 如果已經匹配了,就不要繼續DFS了 if(matched) return ; // 正則表示式到結尾了 if(pj == plen){ // 如果文字串也到結尾了 if(ti == tlen) matched = true; return ; } // 下面是回溯法的“for迴圈”判斷這一步有幾種可能 // 1、正則表示式當前字元為" * " if(patten[pj] == '*'){ // 可以匹配0個或者多個字元 for(int i = 0; i < tlen - ti; i++) match(ti + i, pj + 1, text, tlen, patten, plen); } // 2、正則表示式當前字元為" ? " else if(patten[pj] == '?'){ // 匹配0個任意字元 match(ti, pj + 1, text, tlen, patten, plen); // 匹配1個任意字元 match(ti + 1, pj + 1, text, tlen, patten, plen); } // 3、正則表示式當前字元與文字串相等 else if(patten[pj] == text[ti]){ match(ti + 1, pj + 1, text, tlen, patten, plen); } // 否則就回溯 } int main() { match(0, 0, "abcdef", 6, "a?c*f", 5); cout<<matched<<endl; return 0; }