|
| 1 | +package com.thealgorithms.dynamicprogramming; |
| 2 | + |
| 3 | +public class RegularExpressionMatching { |
| 4 | + |
| 5 | + /** |
| 6 | + * Function to implement regex matching with '.' and '*'. |
| 7 | + * '.' Matches any single character |
| 8 | + * '*' Matches zero or more of the preceding element |
| 9 | + * |
| 10 | + * @param s input string |
| 11 | + * @param p pattern string |
| 12 | + * @return true if the string matches the pattern, false otherwise |
| 13 | + */ |
| 14 | + public boolean isMatch(String s, String p) { |
| 15 | + Boolean[][] memo = new Boolean[s.length() + 1][p.length() + 1]; |
| 16 | + return dp(0, 0, s, p, memo); |
| 17 | + } |
| 18 | + |
| 19 | + private boolean dp(int i, int j, String s, String p, Boolean[][] memo) { |
| 20 | + if (memo[i][j] != null) return memo[i][j]; |
| 21 | + |
| 22 | + boolean ans; |
| 23 | + if (j == p.length()) { |
| 24 | + // If pattern is finished, string must also be finished |
| 25 | + ans = (i == s.length()); |
| 26 | + } else { |
| 27 | + // Check if first character matches |
| 28 | + boolean firstMatch = (i < s.length() && |
| 29 | + (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.')); |
| 30 | + |
| 31 | + // Handle '*' in the pattern |
| 32 | + if (j + 1 < p.length() && p.charAt(j + 1) == '*') { |
| 33 | + // Two options: |
| 34 | + // 1. Skip the "x*" in the pattern |
| 35 | + // 2. If firstMatch is true, consume one char from string |
| 36 | + ans = dp(i, j + 2, s, p, memo) || (firstMatch && dp(i + 1, j, s, p, memo)); |
| 37 | + } else { |
| 38 | + ans = firstMatch && dp(i + 1, j + 1, s, p, memo); |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + memo[i][j] = ans; |
| 43 | + return ans; |
| 44 | + } |
| 45 | + |
| 46 | + // ----------------------- |
| 47 | + // Main function with test cases |
| 48 | + // ----------------------- |
| 49 | + public static void main(String[] args) { |
| 50 | + RegularExpressionMatching solution = new RegularExpressionMatching(); |
| 51 | + |
| 52 | + String[][] testCases = { |
| 53 | + {"aa", "a", "false"}, |
| 54 | + {"aa", "a*", "true"}, |
| 55 | + {"ab", ".*", "true"}, |
| 56 | + {"mississippi", "mis*is*p*.", "false"}, |
| 57 | + {"ab", ".*c", "false"}, |
| 58 | + {"aaa", "a*a", "true"}, |
| 59 | + {"aab", "c*a*b", "true"}, |
| 60 | + {"", ".*", "true"}, |
| 61 | + {"", "", "true"}, |
| 62 | + {"abcd", "d*", "false"} |
| 63 | + }; |
| 64 | + |
| 65 | + System.out.println("Testing Regular Expression Matching (DP with Memoization)\n"); |
| 66 | + |
| 67 | + for (String[] test : testCases) { |
| 68 | + String s = test[0]; |
| 69 | + String p = test[1]; |
| 70 | + boolean expected = Boolean.parseBoolean(test[2]); |
| 71 | + boolean result = solution.isMatch(s, p); |
| 72 | + System.out.printf("Input: s = \"%s\", p = \"%s\" | Output: %b | Expected: %b | %s\n", |
| 73 | + s, p, result, expected, (result == expected ? "✅" : "❌")); |
| 74 | + } |
| 75 | + } |
| 76 | +} |
0 commit comments