Wildcard Matching

'?' Matches any single character.

'*' Matches any sequence of characters(including the empty sequence).

 

The matching should cover the entireinput 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

Given [0,1,0,2,1,0,1,3,2,1,2,1],return 6.

 

       思路:本题与《Regular Expression Matching》类似,解题思路也可以照搬:在模式p中,一旦遇到字符’*’,就将从p+1开始于s+i(i=0,1,2,...)进行匹配,直到找到匹配的位置。但是需要注意一点,如果到了s的最后还是没能匹配的话,整个匹配过程就应该结束了,不应该在回退回去,去看s+i+1是否与p+1匹配,因为是没有意义的,代码如下:

int isMatchcore(char*s, char* p, int *exitflag)
{
    if(*s == '\0')
    {
        if(*p == '\0')  return 1;
        if(*p == '*' &&*(p+1) == '\0') return 1;
        *exitflag = 1;
        return 0;
    }
   
    if(*p != '*')
    {
        if(*p == *s ||*p == '?')   returnisMatchcore(s+1, p+1, exitflag);
        return 0;
    }
 
    if(*p == '*')
    {      
        if(*(p+1) =='\0')  return 1;
        int i = 0;
        int slen = strlen(s);
        while(i < slen &&(isMatchcore(s+i, p+1, exitflag)== 0))
        {
            if(*exitflag == 1) 
            {
                return 0;
            }
            i++;
        }
        if(i < slen)    return 1;
        return 0;
    }
}
 
void predealpattern(char*p)
{
    int i = 0;
    int plen = strlen(p);
 
    int j = 0;
    int lastchar = 0;
    for(i = 0; i <=plen; i++)
    {
        if(p[i] != '*'|| lastchar != '*')
        {
            p[j] = p[i];
            j++;
        }
        lastchar = p[i];
    }
}
 
int isMatch_recurse(char*s, char* p)
{
    predealpattern(p);
    int exitflag = 0;
    return isMatchcore(s, p,&exitflag);
}

predealpattern函数用来对模式进行预处理,对于一连串的’*”,比如’****’,只保留一个’*’。这样做是为了减少递归的次数。exitflag的作用就是,一旦匹配到了s的最后还没有匹配成功,则整个匹配过程就应该结束了。开始没有注意到这一点,则在leetcode上测试直接超时。该递归程序最后的测试时间是16ms。下面是非递归版本,原理上是类似的,时间上更快一些,为8ms:

 

int isMatch_loop(char*s, char* p)
{
    char *lastp = NULL;
    char *lasts = NULL;
   
    while(*s != '\0')
    {
        if(*s == *p ||*p == '?')
        {
            s++;    p++;
        }
        else if(*p == '*')
        {
            p++;
            if(*p == '\0')  return 1;
            lastp = p;
            lasts = s;
        }
        else if(lastp != NULL)
        {
            p = lastp;
            s = ++lasts;
        }
        else
        {
            return 0;
        }
    }
 
    while(*p == '*')p++;
    return *p == '\0';
}


参考:

https://github.com/haoel/leetcode/tree/master/algorithms/wildcardMatching

posted @ 2015-08-15 11:01  gqtc  阅读(117)  评论(0编辑  收藏  举报