Visualize

Pattern visualizer

Regular Expression Matching

A star is hard because it has no fixed width — it can cover nothing, or half the text. The table sidesteps that by never deciding how wide a star is: dp[i][j] only asks whether the first i characters of the text match the first j characters of the pattern, and a star gets exactly two ways to answer. Erase yourself, which skips two pattern characters and reads the cell two columns left. Or eat one text character, which is only legal when the character before the star matches, and reads the cell directly above — the same star, one character of text shorter. Everything else is the ordinary case: a matching character or a dot costs one from each side and reads the diagonal. The arrows are those three moves. Animated on: Does "aab" match the pattern "c*a*b", where "." stands for any single character and "*" means zero or more of the character before it?.

A table where a star is two branches: erase the pair, or eat one more character

time O(m*n)space O(m*n)step 1 / 14

dp[i][j]: do the first i characters of "aab" match the first j characters of "c*a*b"?

line 1

Text "aab" against pattern "c*a*b". Row 0 is the empty text, column 0 the empty pattern, and the answer is the bottom-right corner dp[3][5]. Every cell asks the same question about a shorter prefix of each.

Pseudocode
1FUNCTION isMatch(s, p)
2 dp[0][0] <- TRUE
3 FOR j FROM 1 TO LENGTH(p)
4 IF p[j-1] = '*'
5 dp[0][j] <- dp[0][j-2]
6 FOR i FROM 1 TO LENGTH(s)
7 FOR j FROM 1 TO LENGTH(p)
8 IF p[j-1] = '*'
9 dp[i][j] <- dp[i][j-2]
10 IF p[j-2] = s[i-1] OR p[j-2] = '.'
11 dp[i][j] <- dp[i][j] OR dp[i-1][j]
12 ELSE IF p[j-1] = s[i-1] OR p[j-1] = '.'
13 dp[i][j] <- dp[i-1][j-1]
14 RETURN dp[LENGTH(s)][LENGTH(p)]

← / → step · space play · Home restart

Where to practice Dynamic Programming