回溯法(三)——正则表达式匹配问题

  • 遇到特殊字符的时候,我们就有多种处理方式了,也就是所谓的岔路口:
    • “*”有多种匹配方案,可以匹配任意个文本串中的字符,我们就先随意的选择一种匹配方案,然后继续考察剩下的字符。如果中途发现无法继续匹配下去了,我们就回到这个岔路口,重新选择一种匹配方案,然后再继续匹配剩下的字符。
    • "?"有两种匹配方案,匹配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;
}
posted @ 2020-08-12 10:46  程序员曾奈斯  阅读(335)  评论(0)    收藏  举报