leetcode 10. 正则表达式匹配(困难)

10. 正则表达式匹配(困难)

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

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

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

示例 1:

输入:s = "aa" p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

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

示例 3:

输入:s = "ab" p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。

示例 4:

输入:s = "aab" p = "c*a*b"
输出:true
解释:因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。

示例 5:

输入:s = "mississippi" p = "mis*is*p*."
输出:false

思路:

  1. 从后往前匹配:

    设置指针i=s.length-1,j=p.length-1。从后往前匹配,

    1. p[j]==s[i]时,s与p是否匹配取决于s[0:i-1]与p[0:j-1]是否匹配(s的前i个字符与p的前j个字符是否匹配)
    2. p[j]=='.'时可以匹配任一个字符,因此此时s与p是否匹配取决于s[0:i-1]与p[0:j-1]是否匹配
    3. p[j]=='*'时,由于'*' 可以匹配零个或多个前面的那一个元素,需要分情况讨论
      1. p[j-1]==s[i]或p[j-1]=='.',此时'*'可以表示为匹配一个或多个前一个字符,即此时s与p是否匹配取决于s[0:i-1]与p[0:j]是否匹配;此外,'*'也可以表示为匹配0个前一个字符(这是由于从后往前匹配,会出现虽然p[j-1]==s[i],但从前往后匹配时s[i]匹配的为p[i-2]的字符),因此s与p是否匹配也取决于s[0:i]与p[0:j-2]是否匹配.
      2. p[j-1]为其他值时,'*'表示为匹配0个前一个字符,因此s与p是否匹配也取决于s[0:i]与p[0:j-2]是否匹配.。
    4. p[j]为其他值时,s与p不匹配。

    注意:

    (1)在3.1中两种情况为or的关系,只要一种情况匹配,s[0:i]与p[0:j]即匹配。因此 不能采用迭代来写代码,只能采用递归。

    (2)注意边界条件的判断

    1. i=-1,j>=0:此时需要看p[0:j]的情况,若p[0:j]中均是('a-z'/'.'+'*')的组合则匹配,否则不匹配。
    2. i>=0,j=-1 :说明s与p不匹配(s多出来一部分),返回false
    3. i=-1,j=-1 :此时说明s与p匹配,返回True
  2. 从前往后匹配(动态规划)

设置动态规划数组d[i][j]表示s的前i个与p的前j个字符的匹配结果

  1. p[j]==s[i]:s与p是否匹配取决于s[0:i-1]与p[0:j-1]是否匹配,因此du[i][j]=d[i-1][j-1].
  2. p[j]=='.':s与p是否匹配取决于s[0:i-1]与p[0:j-1]是否匹配,因此du[i][j]=d[i-1][j-1].
  3. p[j]=='*':由于'*' 可以匹配零个或多个前面的那一个元素,需要分情况讨论
    1. p[j-1]==s[i]或p[j-1]=='.',此时'*'可以表示为匹配一个或多个前一个字符,即此时s与p是否匹配取决于s[0:i-1]与p[0:j]是否匹配,即d[i][j]=d[i-1][j];此外,'*'也可以表示为匹配0个前一个字符(这是由于从后往前匹配,会出现虽然p[j-1]==s[i],但从前往后匹配时s[i]匹配的为p[i-2]的字符),因此s与p是否匹配也取决于s[0:i]与p[0:j-2]是否匹配,即d[i][j]=d[i][j-2].
    2. p[j-1]为其他值时,'*'表示为匹配0个前一个字符,因此s与p是否匹配也取决于s[0:i]与p[0:j-2]是否匹配,即d[i][j]=d[i][j-2].
  4. 其他情况时,d[i][j]=False.

初始化:

先将d[j][j]全部初始化为False。然后令d[0][0]=True

(1)C++——思路1

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

(2)C+±dp

class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size()+1;
        int n = p.size()+1;
        vector<vector<bool>>  d(m,vector<bool>(n,false));
        d[0][0]=true;
        for(int j=1;j<n;j++){
            if(p[j-1]=='*'){
                d[0][j]=d[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]=='.')
                    d[i][j]=d[i-1][j-1];
                if(p[j-1]=='*'){
                    if(p[j-2]==s[i-1] || p[j-2]=='.')
                        d[i][j]=(d[i-1][j])||(d[i][j-2]);
                    else
                        d[i][j]=d[i][j-2];
                }
            }
        }
        return d[m-1][n-1];
    }
};

(3)python-dp

import numpy as np
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m = len(s)+1
        n = len(p)+1
        d = np.zeros((m,n),dtype = np.int)
        d[0][0]=1
        for j in range (1,n,1):
            if(p[j-1]=='*'):
                d[0][j]=d[0][j-2]
        for i in range(1,m,1):
            for j in range(1,n,1):
                if(p[j-1]==s[i-1] or p[j-1]=='.'):
                    d[i][j] = d[i-1][j-1]
                if(p[j-1]=='*'):
                    if(p[j-2]==s[i-1] or p[j-2]=='.'):
                        d[i][j]=d[i][j-2] or d[i-1][j]
                    else:
                        d[i][j]=d[i][j-2]
        return bool(d[m-1][n-1])

(4)python_1

import numpy as np
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m = len(s)
        n = len(p)
        return self.match(s,p,m-1,n-1)
    
    def match(self,s,p,i,j):
        if i==-1:
            while(j>-1):
                if p[j]=='*':
                    j=j-2
                else:
                    return False
            return True
        elif j==-1:
            return False
        else:
            if p[j]==s[i] or p[j]=='.':
                return self.match(s,p,i-1,j-1)
            elif p[j]=='*':
                if(p[j-1]==s[i] or p[j-1]=='.'):
                    return self.match(s,p,i-1,j) or self.match(s,p,i,j-2)
                else:
                    return self.match(s,p,i,j-2)
            else:
                return False
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值