题:10. 正则表达式匹配

leetcode题:(https://leetcode.cn/problems/regular-expression-matching/)
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

示例 1:
输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:s = "aa", p = "a"
输出:true
解释:因为 '
' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

题解

class Solution {
public:
    /*  分析思路:从字符串末尾开始反向分析
        # dp[i][j]表示到字符串走完i个为止,且到匹配字符走完j个字符为止,能否匹配上,(i j相当于size,对应索引i-1 j-1)
        # 如果i-1与j-1相等,则是普通字符,只需看前一个是不是匹配的,dp[i][j]=dp[i-1][j-1]
        # 如果i-1与j-1不相等
        # 1 如果p[j-1]='.',可匹配任意字符,也是前一个匹配当前就匹配,dp[i][j]=dp[i-1][j-1]
        # 2 如果p[j-1]!='*', 那dp[i][j]=false,确定无法匹配
        # 3 如果p[j-1]='*',则还需结合j-2的字符,让*对j-2的字符匹配0次、1次、多次,有一种能匹配true就可以
        # 如果p[j-2]==s[i-1] 或 p[j-2]=='.' 的情况:
        # 3.1) p[j-2]匹配0次,也就是直接放弃j-1和j-2,则进一步看j-3索引与i-1是否匹配,则dp[i][j]=dp[i][j-2]
        # 3.2) p[j-2]匹配1次,则需看p[j-3]是否匹配s[i-2],dp[i][j]=dp[i-1][j-2]
        # 3.3) p[j-2]匹配多次,也即s[i-1]匹配消耗了,但P末端不变,进一步看s[i-2]是否与p[j-1]匹配,dp[i][j]=dp[i-1][j]
        # 如果p[j-2]!=s[i-1],则直接让a*匹配0次,进一步考察j-3和i-1是否匹配即可,dp[i][j]=dp[i][j-2]
        #
        # 另外还有些特殊情况:
        # 如果s和p都是空串,肯定匹配
        # 如果s不是空串,p是空串,肯定不匹配
        # 如果s是空串,但p不是,如s=""、p="a*b*c*"可匹配,也即对j个字符,看j-1是不是*,不是则不匹配,是则dp[0][j]=dp[0][j-2]
        # 这样就列出了所有状态转移方程
    */
    bool isMatch(string s, string p) {
        int m = s.size(), n = p.size();
        if (m == 0 && n == 0) return true;
        if (m > 0 && n == 0) return false;
        if (n > 0 && p[0] == '*') return false;
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
        dp[0][0] = true; // m=0,n=0时为true
        // 如果i=m=0, j不为0
        for (int j = 1; j <= n; ++j) {
            if (p[j - 1] == '*') {
                dp[0][j] = dp[0][j-2];
            }
        }
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (s[i - 1] == p[j - 1] || p[j - 1] == '.') {
                    dp[i][j] = dp[i - 1][j - 1];
                } else if (p[j - 1] == '*') {
                    if (s[i - 1] == p[j - 2] || p[j - 2] == '.') {
                        dp[i][j] = dp[i][j - 2] || dp[i - 1][j - 2] || dp[i-1][j];
                    } else {
                        dp[i][j] = dp[i][j-2];
                    }
                } else {
                    dp[i][j] = false;
                }
            }
        }
        return dp[m][n];

    }
};
posted @ 2023-07-12 13:08  00lab  阅读(10)  评论(0编辑  收藏  举报