【筆記】JavaScript版數據結構與算法——基礎算法之“正則類”(10. 正則表達式匹配)


正則表達式匹配

1.題目

10. 正則表達式匹配 - 力扣(LeetCode)

給你一個字符串 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 = “cab”
輸出: true
解釋: 因爲 ‘*’ 表示零個或多個,這裏 ‘c’ 爲 0 個, ‘a’ 被重複一次。因此可以匹配字符串 “aab”。

示例 5:

輸入:
s = “mississippi”
p = “misisp*.”
輸出: false

題目模板

/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
var isMatch = function(s, p) {

};

2.思路分析

在這裏插入圖片描述
這裏的有無模式指的是是否有匹配符”*“或“.”
在這裏插入圖片描述
在這裏插入圖片描述

3.所用到的方法

主要是正則,看其他小夥伴還用到了動態規劃、有向圖、圖的深度遍歷、自動機,6p

4.題解及優化

課程解法

課程視頻源碼通不過。。。

var isMatch = function(s, p) {
  // 對模式變量進行正則篩選
  let modeArr = p.match(/([a-z.]\*)|([a-z]+(?=([a-z.]\*)|$))/g)
  let cur = 0
  let strLen = s.length
  for (let i = 0, len = modeArr.length, m; i < len; i++) {
    // 對於模式分爲三類,.*|a*|cdef
    m = modeArr[i].split('')
    // 如果第二位是*表示是有模式的
    if (m[1] === '*') {
      if (m[0] === '.') {
        cur = strLen
        break
      } else {
        while (s[cur] === m[0]) {
          cur++
        }
      }
    } else {
      for (let j = 0, jl = m.length; j < jl; j++) {
        if (m[j] !== s[cur]) {
          return false
        } else {
          cur++
        }
      }
    }
  }
  return cur === strLen
}

調試後:

var isMatch = function (s, p) {
  p = p.split('')
  p.push('a*')
  p = p.join('')
  console.log(p)
  s = s.split('')
  s.push('aa')
  s = s.join('')
  console.log(s)
  // 對模式變量進行正則篩選
  let modeArr = p.match(/([a-z.]\*)|([a-z]+(?=([a-z.]\*)|$))/g)
  let cur = 0
  let strLen = s.length
  for (let i = 0, len = modeArr.length, m; i < len; i++) {
    // 對於模式分爲三類,.*|a*|cdef
    m = modeArr[i].split('')
    // 如果第二位是*表示是有模式的
    if (m[1] === '*') {
      if (m[0] === '.') {
        cur = strLen
        break
      } else {
        while (s[cur] === m[0]) {
          cur++
        }
      }
    } else {
      for (let j = 0, jl = m.length; j < jl; j++) {
        if (m[j] !== s[cur]) {
          return false
        } else {
          cur++
        }
      }
    }
  }
  return cur === strLen
}

通過在s和p後添加*或其他字母都沒有效果,應該是“.”的問題,代碼進不去m[0] === '.'


課程後面提供的源碼能夠通過

var isMatch = function (s, p) {
  // 邊界情況,如果s和p都爲空,說明處理結束了,返回true,否則返回false
  if (p.length <= 0) {
    return !s.length
  }
  // 判斷p模式字符串的第一個字符和s字符串的第一個字符是不是匹配
  let match = false
  if (s.length > 0 && (p[0] === s[0] || p[0] === '.')) {
    match = true
  }
  // p有模式的
  if (p.length > 1 && p[1] === '*') {
    // 第一種情況:s*匹配0個字符
    // 第二種情況:s*匹配1個字符,遞歸下去,用來表示s*匹配多個s
    return isMatch(s, p.slice(2)) || (match && isMatch(s.slice(1), p))
  } else {
    return match && isMatch(s.slice(1), p.slice(1))
  }
}

在這裏插入圖片描述

其他小夥伴的解法

var isMatch = function (s, p) {
  return new RegExp('^' + p + '$').test(s)
}

在這裏插入圖片描述

動態規劃:狀態轉移方程分析

10、正則表達式匹配

【JavaScript 解法,非正則 】超越 99% 的提交

js動態規劃圖解 - 用圖講述更易懂

不確定的有限自動機,NFA實現正則匹配

不同答案,涉及較廣,值得深入探索,待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章