regular expression (dp solution)

By | December 18, 2015
Share the joy
  •  
  •  
  •  
  •  
  •  
  •  
'.' 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

I wrote in recursion way to solve this problem before. This time I use dp. Let str=”0″+str, reg=”0″+reg. Build dp[][] boolean array with str.length+1 and reg.length+1 for row and column separately. dp[i][j]=true means str[1…i] match reg[1…j]. dp rules are as below: If reg.charAt[j] is not ‘.’ or ‘*’, dp[i][j]=dp[i-1][j-1] && reg.charAt(i)==str.chartAt(j) If reg.charAt[j]==‘.’, dp[i][j]=dp[i-1][j-1] If reg.charAt[j]==‘*’, (1)if dp[i-2][j] is true, then dp[i][j]=true. This considers * has 0 times. (2)If dp[i-1][j+1]==true, move from dp[i][j+1]to right until str[j]!=reg[i-1]. This considers * has 1, 2, or more times.

public static boolean isMatch(String s, String p) {
    s = "$" + s;
    p = "$" + p;
    boolean[][] dp = new boolean[p.length()][s.length()];
    dp[0][0] = true;
    for (int i = 1; i < p.length(); i++) {
        if (p.charAt(i) == '.') {
            for (int j = 1; j < s.length(); j++) {
                dp[i][j] = dp[i - 1][j - 1];
            }
        }
        else if (p.charAt(i) != '*') {
            for (int j = 1; j < s.length(); j++) {
                dp[i][j] = dp[i - 1][j - 1] && p.charAt(i) == s.charAt(j);
            }
        }
        else {  // handle with '*'
            for (int j = 0; j < s.length(); j++) {
                boolean fromTop = dp[i - 1][j] || (i > 1 && dp[i - 2][j]);
                boolean fromLeft = j > 0 && dp[i][j - 1] && (p.charAt(i - 1) == '.' || p.charAt(i - 1) == s.charAt(j));
                dp[i][j] = fromTop || fromLeft;
            }
        }
    }
    return dp[p.length() - 1][s.length() - 1];
}

check my code on github: link