Topic: Hard Mode
Question:
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
» Solve this problem
Method:
OK, hardest question I ever met, and today is July-22-2013.
Basic idea is traverse the p-string from left to right and s-string from right to left.
Create a boolean DP array, and set the first one be true.
If p-index point to a '*', set true from firstmatch to s-length for dp.
Or, traverse s-string from right to firstmatch position, and once the character in s-string has the following conditions: 1. equals to current pointed p-string character; 2. p-string's current pointing character is '?'; 3. the previous dp position is true, then we can set the current dp to true. After that, we keep the record of the minimum true position in dp and give it to a variable which originally is -1.
Then, after this traverse, if the value of variable is still -1, we return false. Or, we put the variable value into firstmatch variable, and go to the next round of traversing p-string.
Much more details should be read from the code.
Code:
public class Solution {
public boolean isMatch(String s, String p) {
// Start typing your Java solution below
// DO NOT write main() function
int pid = 0, firstmatch = 0;
boolean[] dp = new boolean[s.length()+1];
int count = 0;
for (Character c : p.toCharArray()) {
if (c != '*') ++count;
}
if (count > s.length()) return false;
dp[0] = true;
while(pid < p.length()){
if(pid>0 && p.charAt(pid)=='*' && p.charAt(pid-1)=='*'){
pid++;
continue;
}
if(p.charAt(pid) == '*')
for(int i=firstmatch; i<=s.length(); i++)
dp[i] = true;
else{
int match = -1;
for(int i=s.length(); i>firstmatch; i--){
dp[i] = dp[i-1] && (p.charAt(pid) == '?' || p.charAt(pid) == s.charAt(i-1));
if(dp[i]) match = i;
}
if(match < 0) return false;
firstmatch = match;
}
pid++;
}
return dp[s.length()];
}
}
Summary:
Very hard. Spent two days on it. Though I know how it works, still can't figure it out.