package com.interview.leetcode.backtracing;
/**
* Created_By: stefanie
* Date: 14-11-17
* Time: 上午10:16
* Implement wildcard pattern matching with support for '?' and '*'.
* '?' Matches any single character.
* '*' Matches any sequence of characters (including the empty sequence).
*
* The basic idea is to have one pointer for the string and one pointer for the pattern.
* case 1: when p is '?' or matched to s, both p and s go one step
* case 2: when p is '*', mark p position to starIdx, and s position to s, and only p move one step
* case 3: when case 1 and case 2 failed, backtrace if previous '*' is not correctly matched. (starIdx != -1 means have previous '*')
* move p to starIdx + 1, and s to ++matchChar
* in case 3, have this back-tracing, so can't guarantee to O(M + N), in worst case will be O(M*N)
*
* The complexity of the algorithm is O(M*N), where N and M are the lengths of the pattern and input strings. An example of such a worst-case input is:
* input: bbbbbbbbbbbb pattern: *bbbb
*
* Tricks:
* 1. back-tracing the last matched position in s and last '*' position in p, when matchChar using '*'
* so when can't find a solution, could back-tracing to next position in s and p to restart to matchChar
* and it's only back-tracing to the last visited '*'
*/
public class WildcardMatching {
public static boolean isMatch(String str, String pattern) {
int s = 0, p = 0, match = 0, starIdx = -1;
while (s < str.length()){
// advancing both pointers: when p is '?' or matched char
if (p < pattern.length() && (pattern.charAt(p) == '?' || str.charAt(s) == pattern.charAt(p))){
s++;
p++;
}
// * found, only advancing pattern pointer
else if (p < pattern.length() && pattern.charAt(p) == '*'){
starIdx = p;
match = s;
p++;
}
// last pattern pointer was *, advancing string pointer
else if (starIdx != -1){
p = starIdx + 1;
s = ++match;
}
//current pattern pointer is not star, last patter pointer was not *
//characters do not matchChar
else return false;
}
//check for remaining characters in pattern
while (p < pattern.length() && pattern.charAt(p) == '*')
p++;
return p == pattern.length();
}
}