Regular Expression Matching

Match s against p with `.` and `*` — 2D DP over prefix matching.

Hard
Time O(n * m) Space O(n * m)
LeetCode
5 min read
dp string

Problem#

Pattern uses . (any single char) and * (zero or more of the preceding element). Return true iff the entire s matches p.

Examples#

  • s = "aa", p = "a*"true
  • s = "ab", p = ".*"true
  • s = "mississippi", p = "mis*is*p*."false

Approach#

dp[i][j] = does s[:i] match p[:j]. Base: dp[0][0] = true. For p[j-1] == '*': dp[i][j] = dp[i][j-2] (zero copies) OR (dp[i-1][j] AND s[i-1] matches p[j-2]). Else literal/dot: dp[i][j] = dp[i-1][j-1] && (p[j-1] == '.' || p[j-1] == s[i-1]).

Solution#

Regex Matching
class Solution {
public:
bool isMatch(string s, string p) {
int n = s.size(), m = p.size();
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));
dp[0][0] = true;
for (int j = 2; j <= m; ++j)
if (p[j - 1] == '*') dp[0][j] = dp[0][j - 2];
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (p[j - 1] == '*') {
dp[i][j] = dp[i][j - 2] ||
(dp[i - 1][j] && (p[j - 2] == '.' || p[j - 2] == s[i - 1]));
} else {
dp[i][j] = dp[i - 1][j - 1] && (p[j - 1] == '.' || p[j - 1] == s[i - 1]);
}
}
}
return dp[n][m];
}
};

Editorial#

The * case has two branches: “zero copies of the preceding element” (drops two chars from p) or “one more match of that element” (drops one char from s). The first row pre-handles empty s matched against a*b*c* style patterns.

Complexity#

  • Time: O(n * m).
  • Space: O(n * m).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.