diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/RegularExpressionMatching.java b/src/main/java/com/thealgorithms/dynamicprogramming/RegularExpressionMatching.java new file mode 100644 index 000000000000..6a15f4528d06 --- /dev/null +++ b/src/main/java/com/thealgorithms/dynamicprogramming/RegularExpressionMatching.java @@ -0,0 +1,44 @@ +package com.thealgorithms.dynamicprogramming; + +/** + * Class for Regular Expression Matching using Dynamic Programming. + */ +public class RegularExpressionMatching { + + /** + * Determines if the input string matches the given pattern. + * + * @param s the input string + * @param p the pattern string (may contain '.' and '*') + * @return true if the string matches the pattern, false otherwise + */ + public boolean isMatch(final String s, final String p) { + final Boolean[][] memo = new Boolean[s.length() + 1][p.length() + 1]; + return dp(0, 0, s, p, memo); + } + + private boolean dp(final int i, final int j, final String s, final String p, final Boolean[][] memo) { + if (memo[i][j] != null) { + return memo[i][j]; + } + + final boolean ans; + if (j == p.length()) { + ans = (i == s.length()); + } else { + final boolean firstMatch = (i < s.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.')); + + if (j + 1 < p.length() && p.charAt(j + 1) == '*') { + // Two options: + // 1. Skip the pattern with '*' + // 2. Use '*' to match one character + ans = dp(i, j + 2, s, p, memo) || (firstMatch && dp(i + 1, j, s, p, memo)); + } else { + ans = firstMatch && dp(i + 1, j + 1, s, p, memo); + } + } + + memo[i][j] = ans; + return ans; + } +} diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/RegularExpressionMatchingTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/RegularExpressionMatchingTest.java new file mode 100644 index 000000000000..a29a7b57419a --- /dev/null +++ b/src/test/java/com/thealgorithms/dynamicprogramming/RegularExpressionMatchingTest.java @@ -0,0 +1,28 @@ +package com.thealgorithms.dynamicprogramming; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; + +/** + * Test class for RegularExpressionMatching. + */ +public class RegularExpressionMatchingTest { + + @Test + public void testBasicCases() { + final RegularExpressionMatching matcher = new RegularExpressionMatching(); + + // Test cases from the problem + assertFalse(matcher.isMatch("aa", "a")); + assertTrue(matcher.isMatch("aa", "a*")); + assertTrue(matcher.isMatch("ab", ".*")); + assertFalse(matcher.isMatch("mississippi", "mis*is*p*.")); + assertFalse(matcher.isMatch("ab", ".*c")); + assertTrue(matcher.isMatch("aaa", "a*a")); + assertTrue(matcher.isMatch("aab", "c*a*b")); + assertTrue(matcher.isMatch("", ".*")); + assertTrue(matcher.isMatch("", "")); + assertFalse(matcher.isMatch("abcd", "d*")); + } +}