[LeetCode] 10. Regular Expression Matching(正则匹配)

Description

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*' where:
给定一输入字符串 s 和匹配规则 p,实现一个正则表达式引擎,要求能支持 '.''*' 的匹配,其中:

  • '.' Matches any single character.
    '.' 匹配任意单个字符。​​​​
  • '*' Matches zero or more of the preceding element.
    '*' 将其前面一个元素匹配 0 或多次。

The matching should cover the entire input string (not partial).
匹配应该针对整个字符串进行(非部分)。

Examples

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 = "c*a*b"
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 = "mis*is*p*."
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.

Solution

这题的做法有点像最长公共子序列。定义 dp(i, j) 表示 s[0, i]p[0, j] 的匹配结果(字符串下标从 1 开始):

  1. dp(0, 0) = true(空串匹配空串);

  2. s[i] == p[j],显然,dp(i, j) = dp(i - 1, j - 1)

  3. p[j] == '.',自然也能匹配,dp(i, j) = dp(i - 1, j - 1)

  4. p[j] == '*',则又有以下几种情况:

    1. s[i] != p[j]:则此时不能匹配任何字符,dp(i, j) = dp(i, j - 2)

    2. s[i] == p[j]p[j - 1] == '.':此时以下三种情况都可以匹配

      1. dp(i, j) = dp(i - 1, j)(匹配多个字符)

      2. dp(i, j) = dp(i, j - 1)(匹配一个字符)

      3. dp(i, j) = dp(i, j - 2)(不匹配任何字符)

代码如下

class Solution {
    fun isMatch(s: String, p: String): Boolean {
        val dp = Array(s.length + 1) { BooleanArray(p.length + 1) }
        dp[0][0] = true
        for (i in p.indices) {
            if (p[i] == '*' && dp[0][i - 1]) {
                dp[0][i + 1] = true
            }
        }

        for (i in s.indices) {
            for (j in p.indices) {
                doMatching(s, i, p, j, dp)
            }
        }
        return dp.last().last()
    }

    private fun doMatching(
        s: String,
        i: Int,
        p: String,
        j: Int,
        dp: Array<BooleanArray>
    ) {
        if (p[j] == '.') {
            dp[i + 1][j + 1] = dp[i][j]
        }
        if (p[j] == s[i]) {
            dp[i + 1][j + 1] = dp[i][j]
        }
        if (p[j] == '*') {
            if (p[j - 1] != s[i] && p[j - 1] != '.') {
                dp[i + 1][j + 1] = dp[i + 1][j - 1]
            } else {
                dp[i + 1][j + 1] = (dp[i + 1][j] || dp[i][j + 1] || dp[i + 1][j - 1])
            }
        }
    }
}
原文地址:https://www.cnblogs.com/zhongju/p/14197001.html