正则表达式匹配-leetcode刷题笔记

165 阅读2分钟

题目链接: leetcode.cn/problems/re… 题目描述 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

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

这题是动态规划的经典题目,我们定义一个二维的数组dp。 dp[i][j]表示,s的[0,i-1]和p的[0,j-1]是否匹配。

状态转移

  1. 当s[i-1]=p[j-1]或p[j-1] = '.' 时,dp[i][j] = dp[i-1][j-1];
  2. 当p[j-1] = '*'时
    • 当s[i-1]=p[j-2]或p[j-2]='.',说明*前面的字符可以和s[i-1]匹配,就是p[j-1]重复几次的问题。如果重复0次则dp[i][j] = dp[i][j-2];重复一次则dp[i][j] = dp[i-1][j-2];重复多次则dp[i][j] = dp[i-1][j]。
    • 当s[i-1]!=p[j-2]时,则p[j-2]重复0次,dp[i][j] = dp[i][j-2]; 代码
bool isMatch(string s, string p) {
		// 如果s不为空,p为空,直接返回false
        if(s.size() && p.empty()){

            return false;

        }
		// 两个都为空返回true
        if(s.empty() && p.empty()){

            return true;

        }

        int sLen = s.size();

        int pLen = p.size();

        bool dp[sLen+1][pLen+1];

        memset(dp, false, (sLen+1)*(pLen+1));

        dp[0][0] = true;
		// 初始化
        for(int j=1;j<=pLen;j++){

            if(p[j-1] == '*'){

                dp[0][j] = dp[0][j-2];

            }

        }

        for(int i=1;i<=sLen;i++){

            for(int j=1;j<=pLen;j++){
				// 当s[i-1]=p[j-1]或p[j-1] = '.' 时,dp[i][j] = dp[i-1][j-1];
                if(s[i-1] == p[j-1] || p[j-1] == '.'){

                    dp[i][j] = dp[i-1][j-1];

                }else if(p[j-1] == '*'){
					// 当s[i-1]=p[j-2]或p[j-2]='.',说明*前面的字符可以和s[i-1]匹配,就是p[j-1]重复几次的问题。如果重复0次则dp[i][j] = dp[i][j-2];重复一次则dp[i][j] = dp[i-1][j-2];重复多次则dp[i][j] = dp[i-1][j],三者只要有一个为true,则dp[i][j]就为true。
                    if(p[j-2] == s[i-1] || p[j-2] == '.'){

                        dp[i][j] = dp[i][j-2] || dp[i-1][j-2] || dp[i-1][j];

                    }else {
						// 当s[i-1]!=p[j-2]时,dp\[i][j] = dp\[i][j-2];
                        dp[i][j] = dp[i][j-2];

                    }

                }

            }

        }

        return dp[sLen][pLen];

    }