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

全匹配问题,也就是正则式的问题,题目要求两个字符串是否匹配,?代表任意一个字母,*代表任意个字母,也可以是0个。

第一次写的时候出现了很多问题,我用了递归,但由于*代表的是任意字母组合,因此也就比较麻烦,而第一次写出的代码,虽然在本地可以运行成功,但是提交的时候超时。代码如下:

public static boolean isMatch(String s, String p)  {
        char[] str1 = s.toCharArray();
        char[] str2 = p.toCharArray();
        int num = 0;
        for( int i =0;i<p.length();i++){
        	if( str2[i] == '*')
        		num++;
        }
        num = s.length() - p.length() + num;
        System.out.println( s.length()+"  "+p.length()+"  "+num);

        return Match(str1,str2,0,0,num);
 }
	
	public static boolean Match(char[] str1,char[] str2,int a,int b,int num) {//num 表示*可以代表的字符数
		if ( num<0 )
			return false;
		int len1 = str1.length,len2 = str2.length;
		if( a == len1 && b == len2)//两个数组都走到头了
			return true;
		
		if( a == len1 && str2[b] != '*')//只有第一个数组走到头了
			return false;
		else if ( a == len1 && str2[b] == '*'){
			while( b < len2 && str2[b] == '*')
				b++;
			if( b == len2)
				return true;
			else
				return false;
		}
		if( b == len2 ) //只有第二个数组走到头了
			return false;
		
		if( str1[a] == str2[b] || str2[b] == '?'){//遇到相同的字母或者?
			while( a<len1 && b<len2 && str1[a] == str2[b]){
				a++;
				b++;
			}
			return Match(str1,str2,a++,b++,num);
		}
		
		if( str2[b] == '*'){        //遇到*
			while( b<len2 && str2[b] == '*')		//连着的*相当于一个*
				b++;
			if( b == len2 )
				return true;
			for( int i = a,j = b,k = num;i<len1 ;){
				k = num;
				j = b;
				while( i<len1 && j<len2 && str1[i] != str2[b]){		//寻找*后匹配str[b]的字符
					i++;
					k--;
				}
				while( i<len1 && j<len2 && (str1[i] == str2[j] || str2[j] == '?' )){  //之后的字符也要匹配
					i++;
					j++;
				}
				if( k<0)
					continue;
				if( i<len1 && j<len2 && str1[i] != str2[j] && str2[j] != '*')//如果不匹配是因为字符不一样且不是?
					continue;
				else if( Match(str1,str2,i,j,k) )
					return true;
				
			}
			
		
		
		}
		
		return false;
	}

 然后发现了关键的一点:   1.当str1与str2分别到了i和j的时候。同时在str2[j]的位置遇到了*(后面还有别的*的情况下)。

             2.之前的方法是,找str1[i](包括str1[i])之后遇到的所有的str2[j]之后的第一个字母a(非*),然后再按照之前的规则进行匹配,遇到下一个*的时候也会按照刚才的规则进行判断,一旦,错误,将回到第一个*的地方重新进行判断。

             3.这里就存在一个可以优化的点,就是在遇到下一个*的时候,如果已经匹配成功,那么就算之后匹配失败,其实也不用重新返回第一个*来进行判断,只需要回到当前的*处接着判断就可以了,这样的话其实不用递归会比较好写一点。

代码如下:

public static boolean isMatch(String s, String p)  {
	int len1 = s.length(),len2 = p.length();
	char[] str1 = s.toCharArray();
        char[] str2 = p.toCharArray();
        int i = 0, j = 0, pre = -1,before_i = -1,before_j = -1;
		while( i < len1 ){
			if( j < len2 && (str1[i] == str2[j] || str2[j] == '?')){
				i++;
				j++;
			}
			else if( j < len2 && str2[j] == '*'){
				before_i = i;
				before_j = j;
				j++;
			}else if( before_i != -1){
				i = before_i;
				j = before_j+1;
				before_i++;
			}else
				return false;
		}
		while( j<len2 && str2[j] == '*')
			j++;
		if( j == len2 )
			return true;
		else
			return false;		
		
 }

 最后是基本接近最快。