10. Regular Expression Matching

Leetcode Diary

Posted by Xudong on July 6, 2020

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

Thoughts

\[dp[i][j]= \begin{cases} *= \begin{cases} dp[i][j+2] \ || \ dp[i+1][j] & \text{matched}\\ dp[i][j+2] & \text{not matched} \end{cases} \\ !* = \ matched \ \& \ dp[i+1][j+1] \end{cases}\]
  • 递归
  • 递归 + memory 数组
  • down to top 动态规划

Code(JAVA)

// recursion + memory
private int[][] mem;
public boolean isMatch(String s, String p) {
    mem = new int[s.length()+1][p.length()+1];
    memory(0,0,s,p);
    return mem[s.length()][p.length()] == 1;
}

private boolean memory(int i, int j, String s, String p) {
    if(mem[i][j] != 0)
        return mem[i][j] == 1;
    if(p.isEmpty())  {
        mem[i][j] = s.isEmpty()? 1 : -1;
        return s.isEmpty();
    }
    boolean star = p.length() > 1 && p.charAt(1) == '*';
    boolean match = !s.isEmpty() && 
                    (s.charAt(0) == p.charAt(0) || p.charAt(0)== '.');
    
    boolean res = false;
    if(star) {
        if(match)
            res = memory(i,j+2,s,p.substring(2)) || memory(i+1j,s.substring(1),p);
        else
            res = memory(i,j+2,s,p.substring(2));
    } 
    else
        res = match && memory(i+1,j+1,s.substring(1),p.substrin(1));
    mem[i][j] = res? 1:-1;
    return res;
}
//dynamic programming down to top
public boolean isMatch(String s, String p) {
    boolean[][]dp = new boolean[s.length()+1][p.length()+1];
    //init boundary
    dp[s.length()][p.length()] = true;
    for(int i = s.length(); i>=0; i--){
        for(int j = p.length() -1; j>=0; j--){
            boolean star = j < p.length()-1 && p.charAt(j+1) == '*';
            boolean match = i < s.length() && 
                            j < p.length() && 
                            (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.');
            if(star) {
                if(match)
                    dp[i][j] = dp[i][j+2] || dp[i+1][j];
                else
                    dp[i][j] = dp[i][j+2];
            }
            else
                dp[i][j] = match && dp[i+1][j+1];
        }
    }
    return dp[0][0];
}