1. 程式人生 > 實用技巧 >10. 正則表示式匹配 Regular Expression Matching

10. 正則表示式匹配 Regular Expression Matching

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

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

The matching should cover theentireinput string (not partial).

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

方法一、遞迴

如果沒有*,我們依次比較即可

如果存在*,由於題目要求,*是跟著某個字元後面,我們可以1 、忽略*和*前面的字元 2、s和 *前的字元相同,則匹配s剩下的字元和*前即可

public boolean isMatch(String text, String pattern){
        if ( pattern.isEmpty() ) return text.isEmpty();
        boolean first_match = (!text.isEmpty() &&
                (pattern.charAt(0) == text.charAt(0) ||
                        pattern.charAt(
0) == '.')); if (pattern.length() >= 2 && pattern.charAt(1) == '*'){ return (isMatch(text, pattern.substring(2)) ||(first_match && isMatch(text.substring(1), pattern))); }else{ return first_match && isMatch(text.substring(1), pattern.substring(1)); } }

方法二:動態規劃

我們可以定義一個二維的 DP 陣列,其中 dp[i][j] 表示 s[0,i) 和 p[0,j) 是否 match。

1. P[i][j] = P[i - 1][j - 1], if p[j - 1] != '*' && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
2. P[i][j] = P[i][j - 2], if p[j - 1] == '*' and the pattern repeats for 0 times;
3. P[i][j] = P[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'), if p[j - 1] == '*' and the pattern repeats for at least 1 times.

自底向上

enum Result {
        TRUE, FALSE
    }
    Result[][] memo;
    public boolean isMatch(String text, String pattern){
        memo = new Result[text.length() + 1][pattern.length() + 1];
        return dp(0, 0, text, pattern);
    }

    public boolean dp(int i, int j, String text, String pattern){
        if(memo[i][j] != null){
            return memo[i][j] == Result.TRUE;
        }
        boolean ans;
        if( j == pattern.length()){
            ans = i == text.length();
        }else{
            boolean first_match = ( i < text.length() &&
                    (pattern.charAt(j) == text.charAt(i) ||
                            pattern.charAt(j) == '.'));
            if(j + 1 < pattern.length() && pattern.charAt(j+1) == '*'){
                ans = (dp(i, j + 2, text, pattern) || first_match &&dp(I + 1, j, text, pattern));
            }else{
                ans = first_match && dp(i + 1, j +1, text, pattern);
            }
        }
        memo[i][j] = ans ? Result.TRUE : Result.FALSE;
        return ans;
    }

或者自頂向下

public boolean isMatch(String text, String pattern){
        boolean [][] dp = new boolean[text.length() + 1][pattern.length() + 1];
        dp[text.length()][pattern.length()] = true;

        for (int i = text.length(); i >= 0; i--){
           for (int j = pattern.length() - 1; j>= 0; j--){
               boolean first_match = (i < text.length() &&
                       (pattern.charAt(j) == text.charAt(i) ||
                               pattern.charAt(j) == '.'));
               if(j + 1 < pattern.length() && pattern.charAt(j + 1) == '*'){
                   dp[i][j] = dp[i][j + 2] || first_match && dp[i + 1][j];
               }else{
                   dp[i][j] = first_match && dp[i + 1][j + 1];
               }
           }
        }
        return dp[0][0];
    }

參考連結:

https://leetcode.com/problems/regular-expression-matching

https://leetcode-cn.com/problems/regular-expression-matching