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

Solution

(1) Java

Recursive call, the end condition is both s and p are empty (either null or 0 length). The match first considers '*', then '.' or same char. In '*' case, consider no match or one/more match

   public boolean isMatch(String s, String p) {
        if ((p == null || p.length() == 0) && (s != null && s.length() > 0)) {
            return false;
        }
        if ((p == null && s == null) || (p.length() == 0 && s.length() == 0)) {
            return true;
        }
        if (s == null || p == null) {
            return false;
        }
        if (s.length() == 0 && p.length() > 1 && p.charAt(1) == '*') {
            return isMatch(s, p.substring(2));
        } else if (s.length() == 0 && p.length() >= 1) {
            return false;
        }
        if (p.length() > 1 && p.charAt(1) == '*') {
            if (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') {
                return isMatch(s.substring(1), p) || isMatch(s, p.substring(2));
            } else {
                return isMatch(s, p.substring(2));
            }
        }
        if (p.charAt(0) == '.' || p.charAt(0) == s.charAt(0)) {
            return isMatch(s.substring(1), p.substring(1));
        }
        return false;
    }

(2) Python

关键在于当碰到“*”时,只要考虑(1)不匹配,p要倒退2个字符,s不动(2)一个或多个匹配,p不动,s退一个字符。

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        dp = [[False for x in xrange(len(s)+1)] for y in xrange(len(p)+1)]
        dp[0][0] = True
        for i in xrange(2, len(p)+1):
            if p[i-1] == '*':
                dp[i][0] = dp[i-2][0]
        for i in xrange(1, len(p)+1):
            for j in xrange(1, len(s)+1):
                if i>1 and p[i-1]=='*':
                    if p[i-2]=='.' or p[i-2]==s[j-1]:
                        dp[i][j] = dp[i][j-1] | dp[i-2][j]
                    else:
                        dp[i][j] = dp[i-2][j]
                elif p[i-1]=='.' or p[i-1]==s[j-1]:
                    dp[i][j] = dp[i-1][j-1]
        return dp[len(p)][len(s)]

(3) Scala

object Solution {
    def isMatch(s: String, p: String): Boolean = {
        if (s.length() == 0 && p.length() == 0) {
            return true
        }
        if (p.length() == 0 && s.length() != 0) {
            return false
        }
        if (s.length() == 0 && (p.length() == 1 || p.charAt(1) != '*')) {
            return false
        }
        if (p.length() > 1 && p.charAt(1) == '*') {
            if (s.length() == 0 || (s.charAt(0) != p.charAt(0) && p.charAt(0) != '.')) {
                return isMatch(s, p.substring(2))
            } else if (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') {
                return isMatch(s, p.substring(2)) || isMatch(s.substring(1), p) || isMatch(s.substring(1), p.substring(2))
            } 
        } else if (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') {
            return isMatch(s.substring(1), p.substring(1))
        }
        return false
    }
}

dp version:

object Solution {
    def isMatch(s: String, p: String): Boolean = {
        val dp = Array.ofDim[Boolean](s.length()+1,p.length()+1)
        dp(0)(0) = true
        for (k <- 2 to p.length()) {
            if (p.charAt(k-1) == '*') {
                dp(0)(k) = dp(0)(k-2)
            }
        }
        for (i <- 1 to s.length()) {
            for (j <- 1 to p.length()) {
                if (j > 1 && p.charAt(j-1) == '*') {
                    if (p.charAt(j-2) == s.charAt(i-1) || p.charAt(j-2) == '.') {
                        dp(i)(j) = dp(i)(j-2) || dp(i-1)(j) || dp(i-1)(j-2) // it seems || dp(i-1)(j-2) does not matter
                    } else {
                        dp(i)(j) = dp(i)(j-2)
                    }
                } else if (p.charAt(j-1) == s.charAt(i-1) || p.charAt(j-1) == '.') {
                    dp(i)(j) = dp(i-1)(j-1)
                }
            }
        }
        return dp(s.length())(p.length())
    }
}

results matching ""

    No results matching ""