Hard
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).
Example 1:
Input: s = “aa”, p = “a”
Output: false
Explanation: “a” does not match the entire string “aa”.
Example 2:
Input: s = “aa”, p = “a*”
Output: true
Explanation: ‘*’ means zero or more of the preceding element, ‘a’. Therefore, by repeating ‘a’ once, it becomes “aa”.
Example 3:
Input: s = “ab”, p = “.*”
Output: true
Explanation: “.*” means “zero or more (*) of any character (.)”.
Example 4:
Input: s = “aab”, p = “c*a*b”
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches “aab”.
Example 5:
Input: s = “mississippi”, p = “mis*is*p*.”
Output: false
Constraints:
1 <= s.length <= 201 <= p.length <= 30s contains only lowercase English letters.p contains only lowercase English letters, '.', and '*'.'*', there will be a previous valid character to match.#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
int** cache; // 2D array for caching results
// Helper function to initialize the cache with -1 values (indicating unvisited)
void initializeCache(int sLen, int pLen) {
    cache = (int**)malloc((sLen + 1) * sizeof(int*));
    for (int i = 0; i <= sLen; i++) {
        cache[i] = (int*)malloc((pLen + 1) * sizeof(int));
        for (int j = 0; j <= pLen; j++) {
            cache[i][j] = -1; // -1 indicates an unvisited state
        }
    }
}
// Recursive function to check for matches with caching
bool isMatchHelper(const char* s, const char* p, int i, int j) {
    int sLen = strlen(s);
    int pLen = strlen(p);
    // If pattern is exhausted, check if string is also exhausted
    if (j == pLen) {
        return i == sLen;
    }
    // Check cache to avoid recomputation
    if (cache[i][j] != -1) {
        return cache[i][j];
    }
    // Check if the current characters match
    bool firstMatch = (i < sLen && (s[i] == p[j] || p[j] == '.'));
    bool result;
    if ((j + 1) < pLen && p[j + 1] == '*') {
        // Case with '*' in pattern
        result = (firstMatch && isMatchHelper(s, p, i + 1, j)) || isMatchHelper(s, p, i, j + 2);
    } else {
        // Regular character match
        result = firstMatch && isMatchHelper(s, p, i + 1, j + 1);
    }
    cache[i][j] = result; // Store result in cache
    return result;
}
// Main function to check if `s` matches `p`
bool isMatch(const char* s, const char* p) {
    int sLen = strlen(s);
    int pLen = strlen(p);
    initializeCache(sLen, pLen);
    bool result = isMatchHelper(s, p, 0, 0);
    // Free memory allocated for cache
    for (int i = 0; i <= sLen; i++) {
        free(cache[i]);
    }
    free(cache);
    return result;
}