96. Regular Expression Matching
hardAsked at VercelImplement regex matching with '.' (any char) and '*' (zero or more). Vercel asks this for the 2D DP that handles backtracking cleanly — same shape as their route-pattern matcher with wildcards.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Vercel loops.
- Glassdoor (2025-Q4)— Vercel routing-team onsite; DP-based regex match expected.
- Blind (2026-Q1)— Listed as a Vercel hard.
Problem
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).
Constraints
1 <= s.length <= 201 <= p.length <= 20s contains only lowercase English letters.p contains only lowercase English letters, '.', or '*'.It is guaranteed for each appearance of the character '*', there will be a previous valid character to match.
Examples
Example 1
s = "aa", p = "a"falseExample 2
s = "aa", p = "a*"trueExample 3
s = "ab", p = ".*"trueApproaches
1. Plain recursion
Match char-by-char; on '*', try zero-or-more.
- Time
- exponential
- Space
- O(n)
// Exponential blow-up on patterns like 'a*a*a*' against long inputs.Tradeoff: Memoize.
2. 2D DP (optimal)
dp[i][j] = does s[0..i) match p[0..j)? Three cases: p[j-1] is a char (dp[i-1][j-1] AND chars match); '.' (dp[i-1][j-1]); '*' (dp[i][j-2] for zero copies, or dp[i-1][j] if preceding char matches).
- Time
- O(m*n)
- Space
- O(m*n)
function isMatch(s, p) {
const m = s.length, n = p.length;
const dp = Array.from({length: m + 1}, () => new Array(n + 1).fill(false));
dp[0][0] = true;
for (let j = 1; j <= n; j++) {
if (p[j - 1] === '*') dp[0][j] = dp[0][j - 2];
}
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (p[j - 1] === '.' || p[j - 1] === s[i - 1]) dp[i][j] = dp[i - 1][j - 1];
else if (p[j - 1] === '*') {
dp[i][j] = dp[i][j - 2]; // zero copies
if (p[j - 2] === '.' || p[j - 2] === s[i - 1]) {
dp[i][j] = dp[i][j] || dp[i - 1][j];
}
}
}
}
return dp[m][n];
}Tradeoff: O(mn) time and space. The three cases require careful articulation of what each transition represents.
Vercel-specific tips
Vercel grades the DP recurrence and the three cases. Bonus signal: the empty-string vs pattern-with-stars initialization (dp[0][j] for patterns like 'a*b*' should be true at the * positions). Most candidates miss this row initialization.
Common mistakes
- Forgetting the empty-string-pattern row init (dp[0][j] for j >= 2 with star).
- Confusing 'star matches preceding char' with 'star matches any char' — only the preceding char.
- Off-by-one: dp[i][j] = match for s[0..i) and p[0..j), so accesses use [i-1] and [j-1].
Follow-up questions
An interviewer at Vercel may pivot to one of these next:
- Wildcard Matching (LC 44) — '?' and '*' (different semantics).
- Convert to NFA/DFA for repeated matching against many strings.
- Memoized recursion as an alternative.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why dp[0][j] initialization?
Patterns like 'a*' or 'a*b*' can match the empty string. The init handles this: dp[0][j] = true iff p[j-1] is '*' and dp[0][j-2] is true (the '*' contributes zero copies).
Why dp[i-1][j] for the 'star matches one more' case?
If 'a*' has already consumed some 'a's (dp[i-1][j] is true), we can extend by matching one more 'a' at position i — keeping the same dp[j] (the star pattern remains active).
Practice these live with InterviewChamp.AI
Drill Regular Expression Matching and other Vercel interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →