L10 正则表达式匹配

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

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

说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
示例 1:

输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:

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

1.2021年5月22日21:31:35:今天再看,仍是一脸懵逼,收获如下:
1)dp数组扩增一维,应对空字符串
2)难点在于若为*,如何表示多次重复,参照教程

class Solution {
    public boolean isMatch(String s, String p) {
        if(s == null || p == null) return false;

        int len1 = s.length(), len2 = p.length();
        boolean dp[][] = new boolean[len1 + 1][len2 + 1];

        //若s为空字符串,p不空,但含有*
        dp[0][0] = true;
        for(int j = 1; j < len2 + 1; j++){
            //遍历p字符,其实是从右往左遍历的(不严格)
            if(p.charAt(j - 1) == '*') dp[0][j] = dp[0][j - 2];
            //若当前为星,此时当做0个处理,则继承前面两位的结果
        }

        //递推
        for(int i = 1; i < len1 + 1; i++){
            for(int j = 1; j < len2 + 1; j++){
                if(s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.'){
                    //数组与实际下标相差一,若当前相等,直接继承上一位
                    dp[i][j] = dp[i - 1][j - 1];
                }else if(p.charAt(j - 1) == '*'){
                    //若不相同,但幸运的是当前p为星

                    //星号前的字母若与p当前的字母相同,或者星号前的字母为‘.'
                    if(s.charAt(i - 1) == p.charAt(j -  2) || p.charAt(j - 2) == '.'){
                        dp[i][j] = dp[i][j -  2]    //*表示0个,由于p当前还没有比对,需要与p前推两个位置比对,所以才是dp[i][j -2]
                                || dp[i - 1][j - 2]  //表示1个,s.charAt(i - 1) == p.charAt(j -  2)当前相同,双方都向前推一位,
                                || dp[i - 1][j]; //表示多个,当前相同,s向前推一位,p保持不变
                    } else {
                        dp[i][j] = dp[i][j - 2];
                        //若不相同,星号表示0为,s不变,p向前推两位
                    }
                }
            }
        }
        return dp[len1][len2];
    }
}

2.利用牛客的递推方法:

class Solution {
    public boolean isMatch(String s, String p) {
        if(s == null || p == null) return false;
        char[] str = s.toCharArray();
        char[] pattern = p.toCharArray();
        return judge(str, 0, pattern, 0);
    }
    public boolean judge(char[]str, int i, char[] pattern, int j){
        int len1 = str.length, len2 = pattern.length;
        if(i== len1 && j == len2) return true;
        if(i != len1 && j == len2) return false;
        //if( i== len1 && j != len2) return false;//注意这样不对,后面可能有*
        if(j + 1 < len2 && pattern[j + 1] == '*'){
            if(i < len1 && str[i] == pattern[j] || i< len1 && pattern[j] == '.'){
                return judge(str, i + 1, pattern, j) || judge(str, i, pattern, j + 2)
                        || judge(str, i + 1, pattern, j + 2);//多个, 0个,一个,其中一个可以不写
            }else return judge(str, i, pattern, j + 2);
        }else if(i < len1 && j < len2 && str[i] == pattern[j] || i < len1 && j < len2 && pattern[j]=='.'){
            return judge(str, i+ 1, pattern, j+1);
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值