zoukankan      html  css  js  c++  java
  • [Swift]LeetCode10. 正则表达式匹配 | Regular Expression Matching

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/9883662.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

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

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

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

    Note:

    • s could be empty and contains only lowercase letters a-z.
    • p could be empty and contains only lowercase letters a-z, and characters like . or *.

    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 precedeng 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

    给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。

    '.' 匹配任意单个字符。
    '*' 匹配零个或多个前面的元素。
    

    匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

    说明:

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

    示例 1:

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

    示例 2:

    输入:
    s = "aa"
    p = "a*"
    输出: true
    解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。
    

    示例 3:

    输入:
    s = "ab"
    p = ".*"
    输出: true
    解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
    

    示例 4:

    输入:
    s = "aab"
    p = "c*a*b"
    输出: true
    解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。
    

    示例 5:

    输入:
    s = "mississippi"
    p = "mis*is*p*."
    输出: false

    32ms
     1 enum Result {
     2     case TRUE,FALSE
     3 }
     4 class Solution {
     5     var memo:[[Result?]] = [[Result?]]()
     6     func isMatch(_ s: String, _ p: String) -> Bool {
     7         let col:Int = p.count + 1
     8         let row:Int = s.count + 1
     9         memo = [[Result?]](repeating: [Result?](repeating: nil, count: col), count: row)
    10         return dp(0, 0, s, p)
    11     }
    12     
    13     func dp(_ i:Int,_ j:Int,_ text:String,_ pattern:String) -> Bool
    14     {
    15         if memo[i][j] != nil
    16         {
    17             return memo[i][j] == Result.TRUE
    18         }
    19         var ans:Bool
    20         if j == pattern.count
    21         {
    22             ans = i == text.count
    23         }
    24         else
    25         {
    26             var first_match:Bool = i < text.count &&
    27                                    (pattern.charAt(j) == text.charAt(i) ||
    28                                     pattern.charAt(j) == ".")
    29             if j + 1 < pattern.count && pattern.charAt(j+1) == "*"
    30             {
    31                 ans = dp(i, j+2, text, pattern) || first_match && dp(i+1, j, text, pattern)
    32             }
    33             else
    34             {
    35                 ans = first_match && dp(i+1, j+1, text, pattern)
    36             }
    37         }
    38         memo[i][j] = ans ? Result.TRUE : Result.FALSE
    39         return ans
    40     }
    41 }
    42 extension String {
    43     //获取指定索引位置的字符,返回为字符串形式
    44     func charAt(_ num:Int) -> String
    45     {
    46         guard num < self.count else {
    47             assertionFailure("Index out of range!")
    48             return String()
    49         }
    50         let index = self.index(self.startIndex,offsetBy: num)
    51         return String(self[index])
    52     }
    53 }

    16ms
     1 class Solution {
     2     func isMatch(_ s: String, _ p: String) -> Bool {
     3         let s = Array(s), p = Array(p)
     4         var rec: [[Bool]] = Array(repeating: Array(repeating: false, count: p.count + 1), count: s.count + 1)
     5         
     6         rec[0][0] = true
     7         for i in 0..<p.count {
     8             if p[i] == "*" {
     9                 rec[0][i + 1] = rec[0][i - 1]
    10             }
    11         }
    12         
    13         for i in 0..<s.count {
    14             for j in 0..<p.count {
    15                 if p[j] != "*" {
    16                     if rec[i][j] {
    17                         if p[j] == "." || p[j] == s[i] {
    18                             rec[i + 1][j + 1] = true
    19                         }
    20                     }
    21                 } else {
    22                     if rec[i + 1][j - 1] {
    23                         rec[i + 1][j + 1] = true
    24                     } else if rec[i][j - 1] || rec[i][j + 1] {
    25                         if p[j - 1] == s[i] || p[j - 1] == "."   {
    26                             rec[i + 1][j + 1] = true
    27                         }
    28                     }
    29                 }
    30             }
    31         }
    32 
    33         return rec[s.count][p.count]
    34     }
    35 }

    20ms

     1 class Solution {
     2     func isMatch(_ s: String, _ p: String) -> Bool {
     3         let arrayS = Array(s.characters),
     4         lenS = arrayS.count,
     5         arrayP = Array(p.characters),
     6         lenP = arrayP.count
     7         var dp = [[Bool]](repeating: [Bool](repeating: false, count: lenP + 1), count: lenS + 1)
     8         dp[0][0] = true
     9         for i in 0..<lenP {
    10             if arrayP[i] == "*" && dp[0][i - 1] {
    11                 dp[0][i+1] = true
    12             }
    13         }
    14         for i in 0..<lenS {
    15             for j in 0..<lenP {
    16                 if arrayP[j] == "." {
    17                     dp[i+1][j+1] = dp[i][j]
    18                 }
    19                 if arrayP[j] == arrayS[i] {
    20                     dp[i+1][j+1] = dp[i][j]
    21                 }
    22                 if arrayP[j] == "*" {
    23                     if arrayP[j-1] != arrayS[i] &&
    24                         arrayP[j-1] != "." {
    25                         dp[i+1][j+1] = dp[i+1][j-1]
    26                     } else {
    27                         dp[i+1][j+1] = (dp[i+1][j] || dp[i][j+1] || dp[i+1][j-1])
    28                     }
    29                 }
    30             }
    31         }
    32         return dp[lenS][lenP]
    33     }

    24ms

     1 class Solution {
     2     func isMatch(_ s: String, _ p: String) -> Bool {
     3         var dp = [[Bool]](repeating: [Bool](repeating: false, count: p.count + 1), count: s.count + 1)
     4         // Initial condition: both empty, it's a match.
     5         dp[0][0] = true
     6         let sChars = Array(s)
     7         let pChars = Array(p)
     8         for j in 0..<p.count {
     9             if pChars[j] == "*" && dp[0][j - 1] {
    10                 dp[0][j + 1] = true
    11             }
    12         }
    13         for i in 0..<s.count {
    14             let sChar = sChars[i]
    15             for j in 0..<p.count {
    16                 let pChar = pChars[j]
    17                 if (sChar == pChar || pChar == ".") {
    18                     // If s[i] == p[j] or p[j] == '.', check if dp[i - 1][j - 1] matches.
    19                     dp[i + 1][j + 1] = dp[i][j]
    20                 } else if pChar == "*" {
    21                     // If p[j] == '*', then there are two situations.
    22                     //            j - 1  j
    23                     //      p: ...  x   '*' ...
    24                     //      s: ...  z    y  ...
    25                     //            i - 1  i
    26                     if pChars[j - 1] != sChars[i] && pChars[j - 1] != "." {
    27                         // If x != y and x != '.', we can only count x '*' for 0 times, so check if the previous char before x matches y
    28                         // Here i is guaranteed >= 2 as '*' cannot appear at index 0 in p.
    29                         dp[i + 1][j + 1] = dp[i + 1][j - 1]
    30                     } else {
    31                         // If x == y or x == '.', then there are three situations.
    32                         dp[i + 1][j + 1] = dp[i + 1][j - 1]     // x appears zero times
    33                             || dp[i + 1][j]                     // x appears one time to match y
    34                             || dp[i][j + 1]                     // x appears multiple times: y should be part of match to x '*', so check if char before y is a match to x '*'
    35                     }
    36                 }
    37             }
    38         }
    39         return dp[s.count][p.count]
    40     }
    41 }

    28ms

     1 class Solution {
     2     func isMatch(_ s: String, _ p: String) -> Bool {
     3         let sChars = s.utf8CString
     4         let pChars = p.utf8CString
     5         var dp = Array(repeating: Array(repeating: false, count: pChars.count), count: sChars.count)
     6         dp[0][0] = true
     7         
     8         for i in 0...pChars.count-1 {
     9             dp[0][i] = i == 0 || i > 1 && dp[0][i-2] && pChars[i-1] == 42
    10         }
    11         
    12         for i in 0...sChars.count-1 {
    13             for j in 0...pChars.count-1 {
    14                 guard j > 0 else {
    15                     continue
    16                 }
    17                 
    18                 let pCurrent = pChars[j - 1]
    19                 
    20                 if pCurrent != 42 {
    21                     dp[i][j] = i > 0 && dp[i-1][j-1] && (pCurrent == 46 || pCurrent == sChars[i - 1])
    22                 } else {
    23                     dp[i][j] = dp[i][j-2] || i > 0 && j > 1 && (sChars[i-1] == pChars[j-2] || pChars[j-2] == 46) && dp[i-1][j]
    24                 }
    25             }
    26         }
    27         
    28         return dp[sChars.count-1][pChars.count-1]
    29 
    30 
    31     }
    32 }

    32ms

     1 class Solution {
     2     func isMatch(_ s: String, _ p: String) -> Bool {
     3         let text = Array(s)
     4         let patter = Array(p)
     5         var dp = [[Bool]](repeating: [Bool](repeating: false, count: patter.count+1), count: text.count+1)
     6         dp[text.count][patter.count] = true
     7         for i in stride(from: text.count, to: -1, by: -1) {
     8             for j in stride(from: patter.count-1, to: -1, by: -1) {
     9                 let first_match = (i < text.count && (patter[j] == text[i] || patter[j] == "."));
    10                 if j + 1 < patter.count && patter[j+1] == "*" {
    11                     dp[i][j] = dp[i][j+2] || first_match && dp[i+1][j];
    12                 } else {
    13                     dp[i][j] = first_match && dp[i+1][j+1];
    14                 }
    15             }
    16         }
    17         return dp[0][0];
    18     }
    19 }

    36ms

     1 class Solution {
     2 func isMatch(_ s: String, _ p: String) -> Bool {
     3     guard !p.isEmpty else {
     4         guard s.isEmpty else { return false }
     5         return true
     6     }
     7     
     8     let s = Array(s)
     9     let p = Array(p)
    10     
    11     // matchMatrix[i][j] first i chars in s match p[0...j]
    12     var match = Array(repeating: Array(repeating: false, count: p.count), count: s.count + 1)
    13     
    14     // init for i = 0
    15     for j in 1..<p.count {
    16         if p[j] == "*" {
    17             match[0][j] = j > 1 ? match[0][j-2] : true
    18         }
    19     }
    20     
    21     guard !s.isEmpty else { return match[0][p.count - 1] }
    22     for i in 1...s.count {
    23         if i == 1 {
    24             match[1][0] = p[0] == "." ? true : s[0] == p[0]
    25         }
    26         for j in 1..<p.count {
    27             switch p[j] {
    28             case ".":
    29                 match[i][j] = match[i - 1][j - 1]
    30             case "*":
    31                 if p[j - 1] == "." || s[i - 1] == p[j - 1] { // match preceding element
    32                     match[i][j] = match[i - 1][j] || match[i - 1][j - 1]
    33                 }
    34                 
    35                 guard !match[i][j] else { continue }
    36                 if j > 1 { // match zero element
    37                     match[i][j] = match[i][j - 2]
    38                 }
    39             case s[i - 1]:
    40                 match[i][j] = match[i - 1][j - 1]
    41             default:
    42                 continue
    43             }
    44         }
    45     }
    46     return match[s.count][p.count - 1]
    47 }
    48 
    49 }

    44ms

     1 struct Token {
     2     var char:Character
     3     var isStar:Bool
     4 }
     5 
     6 class Solution {
     7     func isMatch(_ s: String, _ p: String) -> Bool{
     8         let sChars = Array(s), pChars = Array(p)
     9         var dp = Array(repeating: Array(repeating: false, count: pChars.count + 1), count: sChars.count + 1)
    10         dp[0][0] = true
    11 
    12         for i in 0...pChars.count {
    13             // jump over "" vs. "x*" case
    14             dp[0][i] = i == 0 || i > 1 && dp[0][i - 2] && pChars[i - 1] == "*"
    15         }
    16 
    17         for i in 0...sChars.count {
    18             for j in 0...pChars.count {
    19                 guard j > 0 else {
    20                     continue
    21                 }
    22 
    23                 let pCurrent = pChars[j - 1]
    24 
    25                 if pCurrent != "*" {
    26                     dp[i][j] = i > 0 && dp[i - 1][j - 1] && (pCurrent == "." || pCurrent == sChars[i - 1])
    27                 } else {
    28                     dp[i][j] = dp[i][j - 2] || i > 0 && j > 1 && (sChars[i - 1] == pChars[j - 2] || pChars[j - 2] == ".") && dp[i - 1][j]
    29                 }
    30             }
    31         }
    32 
    33         return dp[sChars.count][pChars.count]
    34     }
    35 }

    80ma

     1 class Solution {
     2     
     3     var visited = [[Bool]]()
     4     
     5     func isMatch(_ s: String, _ p: String) -> Bool {
     6         for i in 0..<s.count {
     7             var line = [Bool]()
     8             for j in 0..<p.count {
     9                 line.append(false)
    10             }
    11             visited.append(line)
    12         }
    13         return rec(s, p, 0, 0)
    14     }
    15     
    16     func rec(_ sStr: String, _ pStr: String, _ sindex: Int, _ pindex:Int) -> Bool {
    17         let s = Array(sStr)
    18         let p = Array(pStr)
    19         
    20         if s.count>sindex && p.count>pindex {
    21             if visited[sindex][pindex] {
    22                 return false
    23             } else {
    24                 visited[sindex][pindex] = true
    25             }
    26         }
    27         
    28         if sindex >= s.count && pindex >= p.count {
    29             return true
    30         }
    31         
    32         if pindex < p.count-1 && p[pindex+1] == "*" {
    33             if p[pindex] == "." {
    34                 for i in 0..<s.count-sindex {
    35                     if rec(sStr,pStr,sindex+i,pindex+2) {
    36                         return true
    37                     }
    38                 }
    39                 if rec(sStr, pStr, s.count, pindex+2) {
    40                     return true
    41                 }
    42             } else {
    43                 var i = 0
    44                 while sindex+i < s.count && s[sindex+i] == p[pindex] {
    45                     if rec(sStr, pStr, sindex+i, pindex+2) {
    46                         return true
    47                     }
    48                     i += 1
    49                 }
    50                 if rec(sStr, pStr, sindex+i, pindex+2) {
    51                     return true
    52                 }
    53             }
    54         } else {
    55             if pindex<p.count && sindex<s.count && (p[pindex] == s[sindex] || p[pindex] == ".") {
    56                 return rec(sStr, pStr , sindex+1, pindex+1)
    57             } else {
    58                 return false
    59             }
    60         }
    61         return false
    62     }
    63 }
    64 
    65 //测试
    66 let s = Solution()
    67 
    68 print(s.isMatch("aa", "a*"))
  • 相关阅读:
    LeetCode-Path Sum I & II & III
    LeetCode-Unique Binary Search Trees I & II
    LeetCode-230. Kth Smallest Element in a BST
    LeetCode-98. Validate Binary Search Tree
    LeetCode-450. Delete Node in a BST
    LeetCode-108. Convert Sorted Array to Binary Search Tree
    LeetCode-129. Sum Root to Leaf Numbers
    视频中人体轮廓检测
    新型SVM
    Surveillance Monitering入门学习论文笔记
  • 原文地址:https://www.cnblogs.com/strengthen/p/9883662.html
Copyright © 2011-2022 走看看