Wednesday, January 7, 2015

LeetCode 10: Regular Expression Matching

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
public class Solution {
    public boolean isMatch(String s, String p) {
        // DP problem
        int m = s.length();
        int n = p.length();
        
        // match[i][j] represents if the first i characters of 's' match the first j characters of 'p' or not.
        // Default value: false.
        boolean[][] match = new boolean[m+1][n+1];
        
        // null 's' matches null 'p'
        match[0][0] = true;
        
        // '*' can only appear from the second character of 'p'
        // Supposed 's' is null, e.g., 'p' --- "x*"-true / "x*x*" ==> "x*"-true / "xx*" ==> "x"-false
        for (int i = 2; i <= n; i++)
            if(p.charAt(i-1) == '*')
                match[0][i] = match[0][i-2];
                
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                // Case 1: Current character isn't '*'.
                if (p.charAt(j-1) != '*')
                {
                    // If current characters are equal, s==p only depends if their previous characters are equal or not.
                    // e.g., s = "###a", p = "xxxx.", if "###" equals "xxxx", s == p is true.
                    if (s.charAt(i-1)==p.charAt(j-1) || p.charAt(j-1)=='.')
                        match[i][j] = match[i-1][j-1];
                }
                // Case 2: Current character is '*'.
                else
                {
                    // If both characters equals, match[i][j] is true only when match[i][j-2] or match[i-1][j] is true.
                    // e.g., s = "###a", p = "xxxxa*", if "###a" equals "xxxx" OR "###" equals "xxxxa*", s == p is true.
                    if (s.charAt(i-1)==p.charAt(j-2) || p.charAt(j-2)=='.')
                        match[i][j] =  match[i][j-2] || match[i-1][j];
                    // If both characters don't equal, match[i][j] is true only when match[i][j-2] is true.
                    // e.g., s = "###a", p = "xxxxb*", if "###a" equals "xxxx", s == p is true.
                    else
                        match[i][j] = match[i][j-2];
                }
            }
        }
        
        return match[m][n];
    }
}

No comments:

Post a Comment