LeetCode/正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配

  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素

1. 暴力递归

由于*匹配零个或多个前面元素,所以遍历是有方向的,从后往前递归判断,使问题规模缩小

class Solution {
public:
    bool isMatch(string s, string p) {
    //只要有一种匹配成功就返回真
        int m = s.size();int n = p.size();
        return Match(s,p,m-1,n-1);//从后往前
    }
    bool Match(string &s,string &p,int i,int j){
        //边界条件
        if(i<0&&j<0) return true;//已经匹配完
        else if(j<0) return false;//模板串遍历完,匹配失败
        else if(i<0){//模板串有*可以自己消除
            if(p[j]=='*')  return Match(s,p,i,j-2);
            return false;
        }
        if(s[i]==p[j]||p[j]=='.') return  Match(s,p,i-1,j-1);//匹配一次
        if(p[j]=='*'){
            if(j==0) return false;//前面没数了
            if(s[i]==p[j-1]||p[j-1]=='.')//跟前面的数匹配的话
            {
            //匹配零次前面字符
            bool flag1 = Match(s,p,i,j-2);
            //匹配一次
            bool flag2 = Match(s,p,i-1,j-1);
            //匹配多次
            bool flag3 = Match(s,p,i-1,j);
            return flag1|flag2|flag3;
            }
            else return  Match(s,p,i,j-2);//不匹配的话跳过
        }
        return false;
    }
};

2. 动态规划

显然方法一中有很多重复递归,用而二维数组将其记录,减少重复递归
这里直接从前往后动态规划

class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();

        auto matches = [&](int i, int j) {//匿名函数
            if (i == 0)//匹配失败
                return false;
            if (p[j - 1] == '.') 
                return true;//可以匹配成功
            return s[i - 1] == p[j - 1];//相等匹配成功,不等失败
        };

        vector<vector<int>> f(m + 1, vector<int>(n + 1));//多出来的行列存储边界,默认为0
        f[0][0] = true;//边界条件
        for (int i = 0; i <= m; ++i) {//从左往右
            for (int j = 1; j <= n; ++j) {//从上往下,从1开始,因为第一列为边界0
                if (p[j - 1] == '*') {//第j个字符为*,这里其实默认了模板串第一个不会为*
                    f[i][j] |= f[i][j - 2];//选择跳过,匹配零次
                    if (matches(i, j - 1)) //不跳过的情况,前一个字符可以进行匹配
                        f[i][j] |= f[i - 1][j];//匹配多次
                }
                else if (matches(i, j)) //当前可匹配
                    f[i][j] |= f[i - 1][j - 1];//匹配一次
            }
        }
        return f[m][n];//返回主串前m个字符和模板串前n个字符匹配情况
    }
};
posted @ 2022-06-18 02:08  失控D大白兔  阅读(42)  评论(0编辑  收藏  举报