【leet-code清晰解题思路💯✅】44. 通配符匹配

97 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

题目描述

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。

两个字符串完全匹配才算匹配成功。

说明:

  • s 可能为空,且只包含从 a-z 的小写字母。
  • p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。

示例 3:

输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'

示例 4:

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".

示例 5:

输入:
s = "acdcb"
p = "a*c?b"
输出: false

解题思路

  • 读了题目,发现是典型的动态规划。我们先定义状态m[i][j]表示前i位s与前j位p是否匹配。下面分类讨论得到转移方程
    • 当p[j]=='?'时,可以直接匹配最后一位,得到m[i][j] = m[i-1][j-1]。
    • 当p[j]=='*'时,因为他可以匹配任意字符串,所以对k<=i,只要有一个m[k][j-1]匹配就可以。
    • 当p[j]==s[i]时,也是m[i][j] = m[i-1][j-1]
  • 还要注意初始边界条件,m[0][0] = true,对任意j,只要p[j-1] == '*',m[0][j] = m[0][j-1]
func isMatch2(s string, p string) bool {

   m := make([][]bool, len(s)+1)
   for i := 0; i < len(m); i++ {
      m[i] = make([]bool, len(p)+1)
   }
   m[0][0] = true
   for j := 1; j < len(p)+1; j++ {
      if p[j-1] == '*' {
         m[0][j] = m[0][j-1]
      }
   }
   for i := 1; i <= len(s); i++ {
      for j := 1; j <= len(p); j++ {
         if p[j-1] == '?' {
            m[i][j] = m[i-1][j-1]
         } else if p[j-1] == '*' {
            for k := 0; k <= i && m[i][j] == false; k++ {
               m[i][j] = m[i][j] || m[k][j-1]
            }
         } else {
            if s[i-1] == p[j-1] {
               m[i][j] = m[i-1][j-1]
            }
         }
      }
   }
   return m[len(s)][len(p)]

}

image.png

  • 这里时间比较长的问题是有三重循环。其实最里面的循环根据公式,可以简化为m[i][j] = m[i-1][j] || m[i][j-1],如下:
func isMatch(s string, p string) bool {

   m := make([][]bool, len(s)+1)
   for i := 0; i < len(m); i++ {
      m[i] = make([]bool, len(p)+1)
   }
   m[0][0] = true
   for j := 1; j < len(p)+1; j++ {
      if p[j-1] == '*' {
         m[0][j] = m[0][j-1]
      }
   }
   for i := 1; i <= len(s); i++ {
      for j := 1; j <= len(p); j++ {
         if p[j-1] == '?' {
            m[i][j] = m[i-1][j-1]
         } else if p[j-1]=='*'{

            m[i][j] = m[i-1][j] || m[i][j-1]
         }else {
            if s[i-1]==p[j-1]{
               m[i][j]=m[i-1][j-1]
            }
         }
      }
   }
   return m[len(s)][len(p)]

}

image.png

  • 效果提升还是很明显的