Recursion + Memorization explanation with comments in code (in C++)
\nclass Solution {\npublic:\n    /*\n        dp[i][j]==(-1) means dp[i][j] not calculated yet\n        dp[i][j]==  1 means answer is true\n        dp[i][j]==  0
```\nclass Solution {\npublic:\n    /*\n        dp[i][j]==(-1) means dp[i][j] not calculated yet\n        dp[i][j]==  1 means answer is true\n        dp[i][j]==  0 means answer is false\n    */\n    \n    bool search(string &s,string &pattern,int i,int j,vector<vector<int>>&dp){\n        // i correspond to index in s\n        //and j correspond to index in pattern\n\n        if(i==s.size()&&j==pattern.size()){// both substrings are empty\n            return true;\n        }\n        \n        //We have reched at last character of pattern and it is *, then answer is true\n        if(j==pattern.size()-1&&pattern[j]==\'*\'){\n            return true;\n        }\n\n        //Either of them is empty but not both,then pattern can\'t be matched\n        if(i==s.size()||j==pattern.size()){\n            return false;\n        }\n        \n        //Already calculated,then return value directly\n        if(dp[i][j]!=-1){\n            return dp[i][j];\n        }\n        \n        /*\n         current character in pattern is lowercase letter,\n        then if both characters are matching then make function call with both indices incremented, otherwise if they are not matching return false\n        \n        if current character in pattern is \'?\', then make function call with both indices incremented\n        \n        otherwise current character is *. In that case, * can replace subsequence of any  length in original string.\n        Therefore check for all possibilities of * \n        \n        */\n        \n        if(pattern[j]!=\'*\'&&pattern[j]!=\'?\'){\n            if(pattern[j]!=s[i]){\n                return false;\n            }\n            return dp[i][j]=search(s,pattern,i+1,j+1,dp);\n        }else if(pattern[j]==\'?\'){\n            return dp[i][j]=search(s,pattern,i+1,j+1,dp);\n        }else{\n            bool ans=false;\n            for(int k=i;k<=s.size();k++){\n                ans=search(s,pattern,k,j+1,dp);\n                if(ans){\n                    break;\n                }\n            }\n            return dp[i][j]=ans;\n        }\n    }\n    \n    bool isMatch(string s, string p) {\n        string pattern;\n        // consecutive sequence of * can be replaced with single *\n        // Thereofre pattern will not have any consecutive *\n        for(int i=0;i<p.size();i++){\n            if(pattern.back()==\'*\'&&p[i]==\'*\'){\n                continue;\n            }\n            pattern.push_back(p[i]);\n        }\n        vector<vector<int>>dp(s.size()+1,vector<int>(pattern.size()+1,-1));\n        return search(s,pattern,0,0,dp);\n    }\n};\n```
['Recursion', 'Memoization', 'C']