1. 程式人生 > 實用技巧 >回溯法(三)——正則表示式匹配問題

回溯法(三)——正則表示式匹配問題

  • 遇到特殊字元的時候,我們就有多種處理方式了,也就是所謂的岔路口:
    • “*”有多種匹配方案,可以匹配任意個文字串中的字元,我們就先隨意的選擇一種匹配方案,然後繼續考察剩下的字元。如果中途發現無法繼續匹配下去了,我們就回到這個岔路口,重新選擇一種匹配方案,然後再繼續匹配剩下的字元。
    • "?"有兩種匹配方案,匹配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;
}