zoukankan      html  css  js  c++  java
  • [LeetCode 10.] 正则表达式匹配【hard】

    LeetCode 10. 正则表达式匹配

    这道题是正则表达式的匹配,初始化和状态转移都比较繁琐,需要非常小心,测试样例也给的比较全一些。先做一道简化版的 LeetCode 44. 通配符匹配 会简单一些。

    题目描述

    Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*' where:

    • '.' Matches any single character.​​​​
    • '*' Matches zero or more of the preceding element.

    The matching should cover the entire input string (not partial).

    Example 1:

    Input: s = "aa", p = "a"
    Output: false
    Explanation: "a" does not match the entire string "aa".

    Example 2:

    Input: s = "aa", p = "a"
    Output: true
    Explanation: '
    ' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

    Example 3:

    Input: s = "ab", p = "."
    Output: true
    Explanation: ".
    " means "zero or more (*) of any character (.)".

    Example 4:

    Input: s = "aab", p = "cab"
    Output: true
    Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".

    Example 5:

    Input: s = "mississippi", p = "misisp*."
    Output: false

    Constraints:

    • 0 <= s.length <= 20
    • 0 <= p.length <= 30
    • s contains only lowercase English letters.
    • p contains only lowercase English letters, '.', and '*'.
    • It is guaranteed for each appearance of the character '*', there will be a previous valid character to match.

    解题思路

    这种两个字符串的问题,绝大多数都直接 DP,开个二位数组来做。
    我们定义 dp[i][j] 表示 s[:i]p[:j] 是否匹配,则 dp[len(s)][len(p)] 就是最终要求的答案。

    我们在每一维多开一个元素的空间,用于表示字符串为空的时候的匹配。初始化的时候需要考虑的情况:

    • 若 s 和 p 都为空,dp[0][0] 为 true;
    • 若 s 为空、p 非空,dp[0][j] 可能 true 可能 false,参考 Example 4,当 p 为连续的 "a" 或者 "." 的时候为 true;
    • 若 s 非空、p 为空,dp[i][0] 为 false;

    当 s 和 p 都非空的时候,开始状态转移:

    • 若 sc == pc,s 和 p 往前看一位即可,dp[i][j] = dp[i-1][j-1];
    • 若 pc == '.',当前最后一位仍然匹配,dp[i][j] = dp[i-1][j-1];
    • 若 pc == '',则需要考察前一位的情况,'' 可以匹配 0 位、1 位、或多位:
      • 若 ppc == sc 或者 ppc == '.',以下条件满足其一即可匹配:
        • "a" 或者 "." 匹配 0 次;
        • "a" 或者 "." 匹配 "a" 1 次;
        • "a" 或者 "." 匹配 "aaa" 多次;
      • 若 ppc != sc,只能匹配 0 位,dp[i][j] = dp[i][j-2];

    条件很多很复杂,需要一条一条仔细实现。尤其是匹配多次的情况,可以通过递归推导来实现:若 s[:i] 与 p[:j] 可以匹配2次及以上,则 s[:i-1] 与 p[:j] 也是匹配的。

    参考代码

    /*
     * @lc app=leetcode id=10 lang=cpp
     *
     * [10] Regular Expression Matching
     */
    
    // @lc code=start
    class Solution {
    public:
        bool isMatch(string s, string p) {
            int ns = s.size();
            int np = p.size();
    
            // initialize dp[][]
            vector<vector<bool>> dp(ns+1, vector<bool>(np+1));
            dp[0][0] = true; // empty string match empty pattern
            for (int i=1; i<=ns; i++) {
                dp[i][0] = false; // non-empty string match empty pattern
            }
            for (int j=2; j<=np; j+=2) {
                if (p[j-1] == '*') {
                    dp[0][j] = dp[0][j-2]; // empty string match non-empty pattern
                } else {
                    break;
                }
            } // case "aab" "c*a*b"
    
            for (int i=1; i<=ns; i++) {
                for (int j=1; j<=np; j++) {
                    if (s[i-1] == p[j-1] || p[j-1] == '.') {
                        dp[i][j] = dp[i-1][j-1];
                    } else if (p[j-1] == '*') {
                        if (s[i-1] == p[j-2] || p[j-2] == '.') {
                            // match 0, 1, or n char
                            dp[i][j] = dp[i][j-2] || dp[i][j-1] || dp[i-1][j];
                        } else {
                            dp[i][j] = dp[i][j-2];
                        }
                    } else {
                        dp[i][j] = false;
                    }
                }
            }
            return dp[ns][np];
        }
    };
    // @lc code=end
    

    其他解法

    这篇博客 提供了两种简洁的递归解法,可以对比参考。

  • 相关阅读:
    定时器
    sortable.js 华丽丽的排序
    jqGrid一些操作
    session 共享
    数组排序 和 二分法查找
    关于map
    文件导入
    文件导出
    文件下载
    float 保留两位小数
  • 原文地址:https://www.cnblogs.com/zhcpku/p/14473292.html
Copyright © 2011-2022 走看看