zoukankan      html  css  js  c++  java
  • leetcode刷题笔记四十四 通配符匹配

    leetcode刷题笔记四十四 通配符匹配

    源地址:44. 通配符匹配

    问题描述:

    给定一个字符串 (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 = "ab"
    输出: true
    解释: 第一个 '' 可以匹配空字符串, 第二个 '' 可以匹配字符串 "dce".
    示例 5:

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

    代码补充:

    //递归法 提交超时
    //递归终止条件:
    //1.当p长度为0且s长度为0,返回true;当p长度为0且s长度不为0,返回false
    //2.当s长度为0且p中剩余字符均为'*'返回true,否则返回false
    //递归过程自尾向前
    object test {
      def main(args: Array[String]): Unit = {
        def isMatch(s:String, p:String):Boolean = {
          val ns = s.length
          val np = p.length
    
          //2个递归停止条件
          //p长度为0,需要判断s是否为0,均为0返回true,反之返回false
          if (np == 0) return (ns == 0)
    
          //s长度为0,需要判断p中是否为0
          if (ns == 0) {
            for (elem <- p){
              if (elem != '*') return false
            }
            return true
          }
    
          //如果p尾部为'?'或者p尾部字符等于s尾部字符,去除尾部字符递归
          if (p.charAt(np-1) == '?' || p.charAt(np-1) == s.charAt(ns-1)){
            return isMatch(s.substring(0, ns-1), p.substring(0, np-1))
          }
    	  
          //若p尾部为'*',遍历s串中是否存在与去除'*'的p串匹配
          if (p.charAt(np-1) == '*'){
            for (i <- 0 to ns){
              if (isMatch(s.substring(0, i), p.substring(0, np-1))) return true
            }
          }
    
          return false
        }
    
        val ans = isMatch("adceb","a*b")
        println(ans)
      }
    }
    
    
    //动态规划
    //起始状态:dp(0)(0) = true
    //状态转换方程:
    //1.s(i) == p(j) || p(j) == '?'
    //dp(i+1)(j+1) = dp(i)(j)
    //2.p(j) == '*'
    //若*与空串匹配,形如ab与ab* =》dp(i+1)(j+1) = dp(i+1)(j)
    //若*与非空串匹配,形如abc与ab* =》dp(i+1)(j+1) = dp(i)(j+1)
    //这种情况下需要继续判断*是否继续匹配
    object Solution {
        def isMatch(s: String, p: String): Boolean = {
            val ns = s.length
            val np = p.length
            val dp = Array.ofDim[Boolean](ns+1, np+1)
            dp(0)(0) = true 
    
            //初始化,将s为0 p全为*的位置标记
            for (i <- 0 to np-1){
                if (dp(0)(i) && p.charAt(i) == '*') dp(0)(i+1) = true
            }
    
            for (i <- 0 to ns-1){
                for(j <- 0 to np-1){
                    if (p.charAt(j) == '*') dp(i+1)(j+1) = dp(i)(j+1) || dp(i+1)(j)
                    else if(p.charAt(j) == '?' || s.charAt(i) == p.charAt(j)) dp(i+1)(j+1) = dp(i)(j)
                }
            }
    
            return dp(ns)(np)
        }
    }
    
  • 相关阅读:
    [TJOI2015]棋盘
    [FJOI2017]矩阵填数——容斥
    [ZJOI2016]小星星
    [HEOI2013]SAO ——计数问题
    ZJOI2008 骑士
    莫队算法——暴力出奇迹
    可持久化线段树
    dij与prim算法
    LCA 最近公共祖先
    Linux 设置交换分区
  • 原文地址:https://www.cnblogs.com/ganshuoos/p/13216723.html
Copyright © 2011-2022 走看看