【刷题日记】-leetcode10. 正则表达式匹配

91 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

题目描述

image.png

题目释义

给定2个字符串

  • s代表需要匹配的字符串
  • p代表正则表达式
  • 规定两个匹配符号,'.'代表任意字符,'*'代表匹配0或n个前面的字符

解题思路

题目需要求出s是否满足p的匹配条件,其实就是我们常用的正则匹配。整个s的匹配度可以拆成无数个字符的匹配,所以很容易想到动态规划的解题思路。

即规定一个dp[i][j],i是s的字符索引,j是p的字符索引,判断s字符的(0,i)和p字符串的(0,j)是否满足正则条件,所以dp[i][j]的值是布尔值。 所以接下来就是寻找dp[i][j]的关系表达式。

p的字符有三种情况

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

即当p[j] = '.'时,s[i]=p[j],则dp[i][j]的值取决于它们之前位置的字符的匹配度,所以i和j的值都应该前移一位,即当前dp[i][j]=dp[i-1][j-1];

  • 字符 如果s[i] = p[j],则dp[i][j] = dp[i-1][j-1];

如果s[i] ≠ p[j],则dp[i][j] = false;

综上,其实 . 的匹配可以和s[i]=p[j]的情况合并。

  • * 因为'*'号是匹配前一个字符,所以这里匹配p的具体字符位置应该是j-1。
  1. 如果s[i] = p[j-1],dp[i][j] = dp[i-1][j] || dp[i][j-2];

    *匹配0或n个,所以这里有两种情况,一种是一个都不匹配,直接匹配前面的,即dp[i][j-2];一种是匹配n个,即当前j不动,i向前移动1位,即dp[i-1][j]。

  2. 如果s[i] ≠ p[j-1],则dp[i][j] = dp[i-1][j-2];

    这里需要注意和普通字符匹配的区别,因为*是匹配0或n个字符,所以它允许匹配不到*号前面的字符,如果s[i] ≠ p[j-1],那么p的字符则需要向前推2个位置,相当于是跳过*号和前面的字符,匹配它们前面的字符。

代码实现

public  boolean isMatch(String s, String p) {
    int m = s.length();
    int n = p.length();

    boolean[][] dp = new boolean[m + 1][n + 1];
    dp[0][0] = true;
    for (int i = 0; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (p.charAt(j-1) == '*'){
                //p[j]是通配符
                //2种情况
                if (matches(s,p,i,j-1)){
                    //s的当前字符和p的前面一个字符相等,比较s的下一个字符是否等于p的前一个字符
                    dp[i][j] = dp[i][j-2] || dp[i-1][j];
                }else {
                    //s的当前字符和p的前面一个字符不相等,则直接舍弃掉这个表达式
                    dp[i][j] = dp[i][j-2];
                }
            }else {
                //p[j]是字符
                if (matches(s,p,i,j)){
                    //如果s[i] = p[j]
                    dp[i][j] = dp[i-1][j-1];
                }
            }
        }
    }
    return dp[m][n];
}

public  boolean matches(String s, String p, int i, int j) {
    if (i == 0) {
        return false;
    }
    if (p.charAt(j - 1) == '.') {
        return true;
    }
    return s.charAt(i-1) == p.charAt(j - 1);
}