90. Regular Expression Matching
hardAsked at RedditImplement regex matching for '.' and '*'. Reddit uses this DP problem to test state-machine thinking — the same shape used when implementing custom rule-based content filters in their AutoModerator engine.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Reddit loops.
- Glassdoor (2026-Q1)— Reddit content-platform hard question.
Problem
Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where: '.' 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, '.', and '*'.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. Recursive backtracking
If p[j+1] === '*', try zero matches (skip p[j..j+1]) or one+ matches (consume s[i] if matches).
- Time
- exponential
- Space
- O(s + p)
function isMatch(s, p) {
function match(i, j) {
if (j === p.length) return i === s.length;
const first = i < s.length && (p[j] === '.' || p[j] === s[i]);
if (j + 1 < p.length && p[j + 1] === '*') {
return match(i, j + 2) || (first && match(i + 1, j));
}
return first && match(i + 1, j + 1);
}
return match(0, 0);
}Tradeoff: Exponential without memo.
2. DP with memoization (optimal)
Same recursion + memo[i][j].
- Time
- O(s * p)
- Space
- O(s * p)
function isMatch(s, p) {
const memo = new Map();
function match(i, j) {
const key = `${i},${j}`;
if (memo.has(key)) return memo.get(key);
let result;
if (j === p.length) result = i === s.length;
else {
const first = i < s.length && (p[j] === '.' || p[j] === s[i]);
if (j + 1 < p.length && p[j + 1] === '*') {
result = match(i, j + 2) || (first && match(i + 1, j));
} else {
result = first && match(i + 1, j + 1);
}
}
memo.set(key, result);
return result;
}
return match(0, 0);
}Tradeoff: Linear in state space. Bottom-up DP would also work.
Reddit-specific tips
Reddit interviewers grade on the 'zero matches' vs. 'one+ matches' branching for *. Bonus signal: walk through 'aa' vs. 'a*' showing both branches at j=0 (try j+=2 = skip; try i+=1 = consume).
Common mistakes
- Treating * as matching any sequence (it modifies the preceding char).
- Forgetting the i < s.length guard before comparing s[i].
- Off-by-one when peeking at p[j+1] without checking bounds.
Follow-up questions
An interviewer at Reddit may pivot to one of these next:
- Wildcard matching (LC 44) — '?' and '*'.
- Edit distance (LC 72).
- Bottom-up DP version.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why two branches for *?
* can match zero (skip the c* pair) or one+ chars (consume s[i] if c matches s[i], stay at j).
What if s and p are both empty?
Match (both pointers at end). The base case j === p.length and i === s.length returns true.
Practice these live with InterviewChamp.AI
Drill Regular Expression Matching and other Reddit interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →