DP bottom-up Java Solution with detailed explanation
\n\t // Bottom Up DP\n    public boolean isMatch(String s, String p) {\n        // corner case\n        if (s == null || p == null)\n            return false;\n
```\n\t // Bottom Up DP\n    public boolean isMatch(String s, String p) {\n        // corner case\n        if (s == null || p == null)\n            return false;\n\n        int m = s.length();\n        int n = p.length();\n\n        boolean[][] dp = new boolean[n + 1][m + 1];\n\n        // 1. dp[0][0] = true, since empty string matches empty pattern\n        dp[0][0] = true;\n\n        // 2. dp[0][i] = false\n        // since empty pattern cannot match non-empty string\n\n        // 3. dp[j][0]\n        // for any continuative \'*\' will match empty string\n        // e.g s=\'aasffdasda\' p=\'*\'/\'**\'/\'***\'....\n        for (int j = 1; j < n + 1; j++) {\n            if (p.charAt(j - 1) == \'*\') {\n                dp[j][0] = dp[j - 1][0];\n            }\n        }\n\n        // 1. if p.charAt(j) == s.charAt(i), match single character\n        // =>>> dp[i][j] = dp[i - 1][j - 1]\n        // 2. if p.charAt(j) == \'?\', \'?\' match single character\n        // =>>> dp[i][j] = dp[i - 1][j - 1]\n\n        // 3. if p.charAt(j) == \'*\', dp[i][j]=dp[i-1][j]||dp[i][j-1]\n        // =>>> a. \'*\' match empty: dp[i][j]=dp[i-1][j]\n        // =>>> b. \'*\' match multiple characters: dp[i][j]=dp[i][j-1]\n\n        for (int i = 1; i < m + 1; i++) {\n            for (int j = 1; j < n + 1; j++) {\n                char charS = s.charAt(i - 1);\n                char charP = p.charAt(j - 1);\n                if (charS == charP || charP == \'?\')\n                    dp[j][i] = dp[j - 1][i - 1];\n                else if (charP == \'*\')\n                    dp[j][i] = dp[j - 1][i] || dp[j][i - 1];\n\n            }\n        }\n\n        return dp[n][m];\n    }\n```
['Dynamic Programming', 'Java']