Implement wildcard pattern matching with support for '?'
and '*'
.
'?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p) Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*") → true isMatch("aa", "a*") → true isMatch("ab", "?*") → true isMatch("aab", "c*a*b") → false
这道题通配符匹配问题还是小有难度的,这道里用了贪婪算法Greedy Alogrithm来解,由于有特殊字符*和?,其中?能代替任何字符,*能代替任何字符串,那么我们需要定义几个额外的指针,其中scur和pcur分别指向当前遍历到的字符,再定义pstar指向p中最后一个*的位置,sstar指向此时对应的s的位置,具体算法如下:
- 定义scur, pcur, sstar, pstar
- 如果*scur存在
- 如果*scur等于*pcur或者*pcur为 '?',则scur和pcur都自增1
- 如果*pcur为'*',则pstar指向pcur位置,pcur自增1,且sstar指向scur
- 如果pstar存在,则pcur指向pstar的下一个位置,scur指向sstar自增1后的位置
- 如果pcur为'*',则pcur自增1
- 若*pcur存在,返回False,若不存在,返回True
class Solution { public: bool isMatch(const char *s, const char *p) { const char *scur = s, *pcur = p, *sstar = NULL, *pstar = NULL; while (*scur) { if (*scur == *pcur || *pcur == '?') { ++scur; ++pcur; } else if (*pcur == '*') { pstar = pcur++; sstar = scur; } else if (pstar) { pcur = pstar + 1; scur = ++sstar; } else return false; } while (*pcur == '*') ++pcur; return !*pcur; } };
这道题考虑看能不能用动态规划Dynamic Programming来解,开始写了个二维dp,发现说内存超了,于是改成了一维dp,发现最后一个test case过不去,一看那个case,字符串长达三万多个,OJ还是一如既往的丧心病狂,看到网上有人用if条件强行跳过这个case (参见这里),但是我感觉既然OJ这么卡内存和时间,估计就是不想我们用DP来解,还是好好掌握上面那种方法比较好,最后还是把DP也贴出来吧,虽然没法通过最后一个test case:
// Cannot pass the last test case class Solution { public: bool isMatch(const char *s, const char *p) { int m = strlen(s), n = strlen(p); vector<bool> dp(m + 1, false); dp[0] = true; for (int j = 0; j < n; ++j) { if (p[j] != '*') { for (int i = 0; i < m; ++i) { dp[i + 1] = dp[i] && (p[j] == s[i] || p[j] == '?'); } } else { int i = 0; while (i < m && !dp[i]) ++i; while (i < m) dp[i++] = true; } } return dp[m]; } };