假设我们用两个指针分别指向s和p字符串中要匹配的位置,首先分析下通配符匹配过程中会有哪些情况是成功:
s的字符和p的字符相等
p中的字符是?
,这时无论s的字符是什么都可以匹配一个
p中遇到了一个*
,这时无论s的字符是什么都没关系
之前的都不符合,但是p在之前的位置有一个*
,我们可以从上一个*
后面开始匹配
s已经匹配完,但是p后面还有很多连续的`*
这里1和2的情况比较好处理,关键在于如何处理3和4的情况。当我们遇到一个*
时,因为之后可能要退回至该位置重新匹配,我们要将它的下标记录下来,比如idxstar
。但是,当我们连续遇到两次4的情况,如何保证我还是能继续匹配s,而不是每次都退回idxstar+1
导致循环呢?所以我们还要记录一个idxmatch
,用来记录用上一个*
连续匹配到的s中的下标。最后,对于情况5,我们用一个循环跳过末尾的*
跳过就行了。
public class Solution {
public boolean isMatch(String s, String p) {
int idxs = 0, idxp = 0, idxstar = -1, idxmatch = 0;
while(idxs < s.length()){
// 当两个指针指向完全相同的字符时,或者p中遇到的是?时
if(idxp < p.length() && (s.charAt(idxs) == p.charAt(idxp) || p.charAt(idxp) == '?')){
idxp++;
idxs++;
// 如果字符不同也没有?,但在p中遇到是*时,我们记录下*的位置,但不改变s的指针
} else if(idxp < p.length() && p.charAt(idxp)=='*'){
idxstar = idxp;
idxp++;
//遇到*后,我们用idxmatch来记录*匹配到的s字符串的位置,和不用*匹配到的s字符串位置相区分
idxmatch = idxs;
// 如果字符不同也没有?,p指向的也不是*,但之前已经遇到*的话,我们可以从idxmatch继续匹配任意字符
} else if(idxstar != -1){
// 用上一个*来匹配,那我们p的指针也应该退回至上一个*的后面
idxp = idxstar + 1;
// 用*匹配到的位置递增
idxmatch++;
// s的指针退回至用*匹配到位置
idxs = idxmatch;
} else {
return false;
}
}
bool isMatch(char* s, char* p) {
char* p_pos=NULL,*s_pos=NULL;
while(*s){ // 这里判断s[i]!='\0'不是字符串结束条件
if(*p == *s || *p == '?'){ // 单个字符匹配的情况,?匹配单个字符
p++;
s++;
continue;
}
if(*p=='*') // 如果当前p为*,因为*可以匹配多个元素,因此需要寻找匹配位置。p_pos为*的下一个位置
p++;
p_pos = p;
s_pos = s;
continue;
}
if(s_pos != NULL){
s_pos++;
s = s_pos;
p = p_pos;
continue;
}
return false;
}
while(*p && *p == '*'){ //如果s处理完了,p还不为空,如果匹配的话,只允许接下来的字符是*
p++;
}
return !*p;
}