10、正则表达式匹配

  1. 10、正则表达式匹配
    1. 说明:
    2. 示例 1:
    3. 示例 2:
    4. 示例 3:
    5. 示例 4:
    6. 示例 5:
  • 题解
    1. 1、递归
    2. 2、动态规划
  • 10、正则表达式匹配

    给你一个字符串 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' 重复了一次。
    

    示例 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、递归

    // 递归回溯求解
    class Solution {
        public boolean isMatch(String s, String p) {
            // 特殊情况
            if (p.isEmpty()) return s.isEmpty();
            // 首字母匹配
            boolean first_match = (!s.isEmpty() && 
                                   (p.charAt(0) == s.charAt(0) || p.charAt(0) == '.'));
            // 递归匹配
            if (p.length() >= 2 && p.charAt(1) == '*') {
                // 忽略 *  或者  * 的多字符匹配
                return (isMatch(s,p.substring(2)) || 
                        (first_match && isMatch(s.substring(1),p)));
            } else {
                // 第一个字符匹配,同时后移一位
                return first_match && isMatch(s.substring(1),p.substring(1));
            }
        }
    }
    

    2、动态规划

    /**
    * dp 求解 自顶而下 实现
    */
    enum Result {
        TRUE,FALSE
    }
    class Solution {
        Result[][] memo;// memo[i][j] 表示,s的前i个字符与p的前j个字符的匹配状态
        
        public boolean isMatch(String s,String p) {
            memo = new Result[s.length() + 1][p.length() + 1];
            return dp(0,0,s,p);
        }
        
        public boolean dp(int i,int j,String s,String p) {
            //  为空,初始化
            if (memo[i][j] != null) {
                return memo[i][j] == Result.TRUE;
            }
            boolean ans;
            
            if (j == p.length()) {
                ans = i == s.length();
            } else {
                boolean first_match = (i < s.length() && 
                                      (p.charAt(j) == s.charAt(i) || 
                                      p.charAt(j) == '.'));
                
                if (j + 1 < p.length() && p.charAt(j + 1) == '*') {
                    // 忽略 * 或者 继续匹配下一个字符
                    ans = dp(i,j+2,s,p) || 
                        first_match && dp(i+1,j,s,p);
                } else {
                    // 字符匹配
                    ans = first_match && dp(i+1,j+1,s,p);
                }
            }
            
            // 更新s的前i个字符与p的前j个字符的匹配状态
            memo[i][j] = ans ? Result.TRUE : Result.FALSE;
            return ans;
        }
    }
    
    /**
        dp 求解 自底而上 
    */
    class Solution {
        public boolean isMatch(String s,String p){
            boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
            dp[s.length()][p,length()] = true;
    
            // 逆向匹配
            for (int i = s.length(); i >= 0; i--) {
                for (int j = p.length() - 1; j >= 0; j--) {
                    // 检查第一个字符是否匹配
                    boolean first_match = (i < s.length() && 
                        (p.charAt(j) == s.charAt(i) ||
                        p.charAt(j) == '.'));
                    
                    if (j + 1 < p.length() && p.charAt(j+1) == '*') { // 模式串下一个是* 
                        // 更新匹配
                        dp[i][j] = dp[i][j+2] || first_match && dp[i+1][j];
                    } else { // 模式串下一个不是 *
                        dp[i][j] = first_match && dp[i+1][j+1];
                    }
                }
            }
            return dp[0][0];// 返回最终结果
        }
    }
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

    💰

    Title:10、正则表达式匹配

    Count:870

    Author:攀登

    Created At:2020-07-26, 00:19:44

    Updated At:2024-06-15, 15:52:32

    Url:http://jiafeimao-gjf.github.io/2020/07/26/10%E3%80%81%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8C%B9%E9%85%8D/

    Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

    ×

    Help us with donation