[LeetCode] 10. Regular Expression Matching

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

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

The matching should cover the entire input string (not partial).正則表達式

Note:express

  • 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:ui

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:spa

Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.

Example 3:code

Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.

Example 4:htm

Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Example 5:blog

Input:
s = "acdcb"
p = "a*c?b"
Output: false

正則表達式匹配。題意是給一個字符串S和一個字符規律P,請你完成S和P的正則匹配。規則以下,點能夠表示/替換任何字符;星號能夠代替0個或多個以前的字符。element

這個題是一個二維DP題。這個題DP的含義不難想,難的是如何處理好各類case。這裏咱們須要明確dp[i][j]的含義,是S的前i個字符與P的前J個字符是否match。爲了看S的前i個字符與P的前J個字符是否match,比較直觀的想法就是去看他們各自以前一個位置的DP狀況,即dp[i - 1][j - 1],可是對於當前位置,會有以下幾種狀況須要考慮。參考了LC中文網一個大神的總結leetcode

1. 若是 p[j] == s[i],那麼dp[i][j] = dp[i-1][j-1]

2. 若是p[j] != s[i],即當前遍歷到的字符不匹配

  2.1. p[j] == "." : dp[i][j] = dp[i-1][j-1],由於點能夠替換任何字符,只要去看以前那一位的字符是否匹配便可。這個case等同於第一個case。

  2.2. p[j] ==" * ",這個又須要細分紅如下兩種狀況。由於星號能夠代替0個多個在他以前的那個字符,因此須要看p[j - 1]和s[i]的狀況

    2.2.1. p[j-1] != s[i] : dp[i][j] = dp[i][j-2]

    這裏設想的是星號去掉了他本身和他本身以前的那個字符,好比這個例子,s = ab, p = abc*

    2.2.2. p[j-1] == s[i] or p[j-1] == "."。星號前面那個字符,能匹配 s[i],或者星號前面那個字符是萬能的。由於星號+點就等同於兩個點,只要看再前面的部分是否匹配便可。好比s == aa, p = a*

時間O(mn)

空間O(mn)

Java實現

 1 class Solution {
 2     public boolean isMatch(String s, String p) {
 3         // corner case
 4         int m = s.length();
 5         int n = p.length();
 6         boolean[][] dp = new boolean[m + 1][n + 1];
 7         dp[0][0] = true;
 8 
 9         // 星號匹配前面0個字符
10         for (int i = 2; i <= n; i++) {
11             if (p.charAt(i - 1) == '*') {
12                 dp[0][i] = dp[0][i - 2];
13             }
14         }
15 
16         for (int i = 1; i <= m; i++) {
17             for (int j = 1; j <= n; j++) {
18                 char sc = s.charAt(i - 1);
19                 char pc = p.charAt(j - 1);
20                 if (sc == pc || pc == '.') {
21                     dp[i][j] = dp[i - 1][j - 1];
22                 } else if (pc == '*') {
23                     // * matches zero preceding letters
24                     if (dp[i][j - 2]) {
25                         dp[i][j] = true;
26                     }
27                     // * matches one preceding letter
28                     // aa - a*
29                     else if (sc == p.charAt(j - 2) || p.charAt(j - 2) == '.') {
30                         dp[i][j] = dp[i - 1][j];
31                     }
32                 }
33             }
34         }
35         return dp[m][n];
36     }
37 }

 

LeetCode 題目總結

相關文章
相關標籤/搜索