LeetCode 10. Regular Expression Matching

Regular Expression Matching

1、原題

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).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch(“aa”,”a”) → false
isMatch(“aa”,”aa”) → true
isMatch(“aaa”,”aa”) → false
isMatch(“aa”, “a*”) → true
isMatch(“aa”, “.*”) → true
isMatch(“ab”, “.*”) → true
isMatch(“aab”, “c*a*b”) → true

原題鏈接

一定要 仔細看題仔細看題

  • .* 是一體的,代表可以匹配任意個任意的字符
  • a* 也一體的 看第七個case,把c*看成匹配一體、把 a*也看成一體的,那麼當c*匹配空字符並且a*匹配兩個字符a,那麼aab跟c*a*b就是匹配的 所以輸出了 true

2、解題思想

這題可以通過 動態規劃 解決,

首先我們可以 定義個 boolean match[i][j]
代表 待匹配串s中從0…i的子串與原串0…就的子串的匹配結果 true 匹配成功 false 匹配失敗。

接下來就是動態規劃的流程了。

1、 找邊界條件

case 1.1、 i == 0 && j == 0

i=0j=0 的時候 那麼 match[i][j] = true 這毫無疑問的 兩個空串匹配肯定是 true

case 1.2、i == 0 && j > 2 && p[j-2] == '*'



i == 0 && j > 2 && p[j-2] == '*' ;
match[i][j] == match[i][j-2]

這爲什麼呢 因爲直接我說過 .* 或者 a* 可以匹配匹配任意個任意的字符
那麼就是說 s=""p=".*"或者 p="a*" 是匹配值 爲什麼 .* 可以匹配空字符

#### case 1.3、 i != 0 && j == 0

i=0j!=0 的時候 那麼 match[i][j] = false 因爲待匹配串長度不爲0 但是原串長度是0 這是無法匹配上的 所以是false

2、 找狀態轉移方程

case 2.1 p[j] != '*"

match[i+1][j+1] = match[i][j] and (s[i] == p[j] or p[j] == '.' )

這種情況最好理解就不多解釋。

case 2.1 p[j] == '*"

因爲我之前說過 .* a* c*是一體的

那麼它們可以匹配0個或者1個或者多個字符

我們一個一個分情況考慮

a、 當前*匹配0個字符
match[i+1][j+1] = match[i+1][j-1]
舉慄
s=”aaa” p=”aaab*” ===> true
b、 當前*匹配1個字符
match[i+1][j+1] = match[i][j-1] && (s[i] == p[j-1] || p[j-1] == '.')
舉慄
s=”aa” p=”a*” ===>true
b、 當前*匹配多個字符
match[i+1][j+1] = match[i][j+1] && (s[i] == p[j-1] || p[j-1] == '.')
舉慄
s=”aaaa” p=”a*” ===>true

3、 編碼

下面貼一下我leetocode ac的代碼

public static boolean isMatch(String s, String p) {

        boolean[][] match = new boolean[s.length() + 1][p.length() + 1];

        match[0][0] = true;
        for (int i = 1; i < p.length(); i++) {
            if (p.charAt(i) == '*') {
                match[0][i + 1] = match[0][i - 1];
            }
        }
        for (int i = 1; i < s.length() + 1; i++) {
            for (int j = 1; j < p.length() + 1; j++) {
                if (p.charAt(j - 1) != '*') {
                    match[i][j] = match[i - 1][j - 1] && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.');
                } else if (p.charAt(j - 1) == '*') {
                    // *匹配0個
                    match[i][j] = (match[i ][j - 2]
                            //   *匹配1個
                            || (match[i - 1][j - 2] && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.'))
                            //   *匹配多個
                            || (match[i - 1][j] && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.'))
                    );
                }

            }
        }

        return match[s.length()][p.length()];

    }

4、 總結

其實這題也可以用遞歸寫出來 但是時間複雜度是指數級 用dp的時間複雜度是O(n^2),
最後如果寫的有什麼不足之處歡迎指定。

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