Wildcard Matching
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
---------------------------------------------------------------Solution #1 recursion, OJ time limit exceeded
class Solution {
public:
bool isMatch(const char *s, const char *p) {
if (*p == '\0') {
return *s == '\0';
}
if (*p == *s || *p == '?') {
return isMatch(s + 1, p + 1);
}
if (*p == '*') {
while (*s != '\0') {
if(isMatch(s,p + 1)) {
return true;
}
s++;
}
}
return false;
}
};
Solution #2, dp with 2d arrays,
class Solution {
public:
bool isMatch(string s, string p) {
int m = p.length(), n = s.length();
vector<vector<bool> > dp(m + 1,vector<bool>(n + 1,false));
dp[0][0] = true;
for (int i = 0; i < m; i++) {
if (p[i] != '*') break;
dp[i + 1][0] = true;
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dp[i][j] && (p[i] == s[j] || p[i] == '?')) {
dp[i + 1][j + 1] = true;
}else if (p[i] == '*') {
if (dp[i][j + 1] || dp[i + 1][j]) {
dp[i + 1][j + 1] = true;
}
}
}
}
return dp[m][n];
}
};
改良版DP,用了一个一维数组,当*p == '*',dp[j]只取决于dp[j - 1],过不了最后一个test case
class Solution {
public:
bool isMatch(string s, string p) {
int m = p.length(), n = s.length();
vector<bool> dp(n + 1,false);
bool diag = true;
dp[0] = true;
for (int i = 0; i < m; i++) {
diag = dp[0];
for (int j = 0; j < n; j++) {
if (diag && (p[i] == s[j] || p[i] == '?')) {
diag = dp[j + 1];
dp[j + 1] = true;
}else if (p[i] == '*') {
diag = dp[j + 1];
if (dp[j] || dp[j + 1]) {
dp[j + 1] = true;
}
}else {
diag = dp[j + 1];
dp[j + 1] = false;
}
}
if (p[i] == '*' && dp[0]) {
dp[0] = true;
}else {
dp[0] = false;
}
}
return dp[n];
}
};
Solution #3, constant space
star用来记录最近*的位置,index用来记录当前*匹配成功后s的位置。*之前全部匹配成功,不用再重复检测。*之后如果匹配失败,回头从star + 1 和 index重新匹配,每匹配失败一次,index增加一位。
class Solution {
public:
bool isMatch(const char *s, const char *p) {
const char *star = NULL;
const char *index = s;
while (*s != '\0') {
if (*s == *p || *p == '?') {
s++;
p++;
}else if (*p == '*') {
star = p;
p++;
index = s;
}else if (star != NULL) {
p = star + 1;
index++;
s = index;
}else return false;
}
while (*p == '*') {
p++;
}
return *p == '\0';
}
};
Java,2维dp
class Solution {
public boolean isMatch(String s, String p) {
List<List<Boolean>> dp = getDP(s, p);
for (int i = 0; i < p.length(); i++) {
for (int j = 0; j < s.length(); j++) {
if (dp.get(i).get(j) && (s.charAt(j) == p.charAt(i) || p.charAt(i) == '?')) {
dp.get(i + 1).set(j + 1, true);
} else if (p.charAt(i) == '*' && (dp.get(i).get(j + 1) || dp.get(i + 1).get(j))) {
dp.get(i + 1).set(j + 1, true);
}
}
}
return dp.get(p.length()).get(s.length());
}
private List<List<Boolean>> getDP(String s, String p) {
int m = s.length();
int n = p.length();
List<List<Boolean>> dp = new ArrayList<>();
for (int i = 0; i < n + 1; i++) {
List<Boolean> inner = new ArrayList<>();
if (i == 0 || (i > 0 && dp.get(i - 1).get(0) && p.charAt(i - 1) == '*')) inner.add(true);
else inner.add(false);
for (int j = 0; j < m; j++) {
inner.add(false);
}
dp.add(inner);
}
return dp;
}
}
No comments:
Post a Comment