leetcode 困难 —— 正则表达式匹配(超详细思路,递归 或 dp)

题目:
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
'
’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

题解

① 递归:
就是考虑每种情况情况
(每种情况写在注释里)

class Solution {
public:
    string sss, ppp;
    bool solve(int a, int b) {
    	// 避免最后 a 匹配完,b 还剩下 "a*b*c*",这种也算完全匹配
        if(a == sss.size()) {
            while(b < ppp.size() - 1) {
                if(ppp[b + 1] == '*') {
                    b = b + 2;
                }
                else {
                    break;
                }
            }
        }
        // 递归终止条件,如果都到了字符串末尾,则完全匹配
        if(a == sss.size() && b == ppp.size()) {
            return true;
        }
        // 递归终止条件,如果其中一个到了字符串末尾,另一个没到末尾,则不是完全匹配
        if((a == sss.size() || b == ppp.size()) && (a + b != sss.size() + ppp.size())) {
            return false;
        }
        // 如果该字符后面有 '*'
        if(b < ppp.size() - 1 && ppp[b + 1] == '*') {
        	// 如果有重复的 "a*a*a*",只用看作一个 'a*',特别的如果存在 '*',例 "a*.*",可以看成 ".*"
            if(b < ppp.size() - 3 && ppp[b + 3] == '*') {
                if(ppp[b + 2] == '.' || ppp[b + 2] == ppp[b]) {
                    return solve(a, b + 2);
                }
            }
            // 如果字符相同,则可以选择不匹配,或者匹配
            if(sss[a] == ppp[b] || ppp[b] == '.') {
                return solve(a + 1, b) || solve(a, b + 2);
            }
            // 如果字符不相同,则只能跳过,并且得跳过两个 '*' 也要被跳过
            else {
                return solve(a, b + 2);
            }
        }
        // 如果该字符后面没有 '*'
        else {
         	// 如果相同则匹配
            if(sss[a] == ppp[b] || ppp[b] == '.') {
                return solve(a + 1, b + 1);
            }
            // 如果不相同则不匹配
            else {
                return false;
            }
        }
    }
    bool isMatch(string s, string p) {
        sss = s;
        ppp = p;
        // 从两个字符串的开头开始进行匹配
        return solve(0, 0);
    }
};

② dp
定义一个数组 dp[i][j],代表 p 字符串前 i 个 和 s 字符串前 j 个是否匹配
首先 dp[0][0] 肯定是匹配的,特别的,类似 “aa” 也和 “” 是匹配的,所以预处理时我们需要考虑
接下来就类似于递归,考虑每种情况

class Solution {
public:
    bool dp[35][35];
    bool isMatch(string s, string p) {
        dp[0][0] = true;
        int f = 2;
        while(f <= p.size()) {
            if(p[f - 1] == '*') {
                dp[f][0] = true;
            }
            else {
                break;
            }
            f = f + 2;
        }
        for(int i = 1; i <= p.size(); i++) {
            for(int j = 1; j <= s.size(); j++) {
                if(p[i - 1] == '*') {
                    dp[i][j] = dp[i - 1][j];
                }
                else if(i < p.size() && p[i] == '*') {
                    if(p[i - 1] == s[j - 1] || p[i - 1] == '.') {
                        dp[i][j] = (dp[i - 1][j - 1] || dp[i - 1][j] || dp[i][j - 1]);
                    }
                    else {
                        dp[i][j] = dp[i-1][j];
                    }
                }
                else if(p[i - 1] == s[j - 1] || p[i - 1] == '.') {
                    dp[i][j] = dp[i - 1][j - 1];
                }
                else {
                    dp[i][j] = false;
                }
            }
        }
        return dp[p.size()][s.size()];
    }
};

猜你喜欢

转载自blog.csdn.net/m0_52212261/article/details/128891928