LeetCode——Wildcard Matching

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


类似于Regular Expression Matching,此题可以采用搜索求解。

但是,在Regular Expression Matching中,"*"之前会指定一个字符,例如:"a*",而Wildcard Matching中的"*"可以匹配任意多的各种字符。

因此,Wildcard Matching的搜索量是大于Regular Expression Matching的。

搜索可以解决小数据,大数据是会超时的。


换一个思路,设数组F[i][j],表示到S串的第i位,P串的第j位是否匹配成功。

例如:

S="ababa",P="a*?",则

F(i, j)
S/P0 'a'1 '*'2 '?'3 '/0'
0 'a'TRUETRUEFALSEFALSE
1 'b'FALSETRUETRUEFALSE
2 'a'FALSETRUETRUEFALSE
3 'b'FALSETRUETRUEFALSE
4 'a'FALSETRUETRUEFALSE
5 '/0'FALSETRUETRUETRUE

假设S的长度为Ls,P的长度为Lp,所求即为F[Ls, Lp]。


现在的关键问题在于,以及得到了F[i, j]如何推到之后的内容。

F[i, j] = true:

1.P[j] == '*', F[i + 1, j] = true

2.P[j + 1] = S[i + 1] || P[j + 1] == '?', F[i + 1, j + 1] = true

F[i, j] = false:

1.F[i + 1, j - 1] == true && P[j] == '*'


这样做提交之后,发现内存超出限制,测试的数据中S和P都非常长。

对空间作优化,可以看出F[i + 1][]只与F[i+1][]和F[i][]有关,与之前的F[i-1]、F[i-2]、F[i-3]、... 、F[0]都没有关系。

因此,可以只要F[i]和F[i+1]。


最终的代码:

class Solution {
public:
    bool initCheck(const char *s, const char *p) {
        int l1 = 0;
        int idx = 0, l2 = 0;
        
        while (s[l1] != '\0') {
            l1++;
        }
        while (p[idx] != '\0') {
            l2 += p[idx++] != '*' ? 1 : 0;
        }
        
        return l1 >= l2;
    }
    
    bool isMatch(const char *s, const char *p) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (!initCheck(s, p)) {
            return false;
        } 
        
        int l = 0;
        while (p[l++] != '\0');
          
        
        bool prev[l], f[l];
        memset(f, false, sizeof(bool) * l);
        memset(prev, false, sizeof(bool) * l);
        
        bool isFirst = true;
        for (int i = 0; i < l; i++) {
            if (p[i] == '*') {
        		f[i] = i == 0 || f[i - 1];
        	}        	
        	else if ((p[i] == '?' || p[i] == *s) && isFirst) {
        		isFirst = false;
        		f[i] = true;
        	}
        	else {
        		break;
        	}
        }
        s++;
        
        while (*(s - 1) != '\0') {
            memcpy(prev, f, l);
            memset(f, false, sizeof(bool) * l);
            
            for (int i = 0; i < l; i++) {
				if (prev[i]) {
					f[i] = f[i] || p[i] == '*';
					f[i + 1] = f[i + 1] || p[i + 1] == '?' || p[i + 1] == *s;
				}
				else if (i == 0 || f[i - 1]) {
					f[i] = f[i] || p[i] == '*';
				}
            }
            s++;
        }	
        
        return f[l - 1];
    }
};




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值