Leetcode 44. Wildcard Matching

问题

https://leetcode.com/problems/wildcard-matching/

解法一(DP)

时间复杂度O(n*m) 空间复杂度 2m 与正则匹配dp实现相同
参考:
http://blog.csdn.net/galaxy_wolf/article/details/51111906

class Solution {
public:
    bool isMatch(string s, string p) {
        bool dp[2][p.size()+1];
        memset(dp, 0, sizeof(dp));
        int cur = 0;
        dp[cur][0] = true;
        for (int i=1; i<=p.size(); ++i)
            if (p[i-1] == '*')
                dp[cur][i] = dp[cur][i-1];
        for (int i=0; i<s.size(); ++i)
        {
            dp[!cur][0] = 0;
            for (int j=1; j<=p.size(); ++j)
            {
                if (p[j-1]=='*')
                {               // 0                1               multi
                    dp[!cur][j] = dp[!cur][j-1] | (dp[cur][j-1]) | dp[cur][j];
                }else{
                    if (dp[cur][j-1] && (p[j-1] == '?' || p[j-1] ==s[i]))
                        dp[!cur][j] = true;
                    else
                        dp[!cur][j] = false;
                }
            }
            cur = !cur;
        }
        return dp[cur][p.size()];
    }
};

解法二(回溯)

由于本题中只会有一种变长匹配”*”, 在出现”*”处我们都要枚举 “*” 匹配0~多个,的情况,如果之后不匹配则要回到”*” 处。如果p中存在多个”*”我们只需要在最后一个出现的”*” 处进行回溯,这是因为如下面的例子:
s:cabcefabcd
p:c*abc*d
此时有两种匹配方案, 第一个* 匹配0个字符第二个* 匹配5个字符
第二种方案, 第一个* 匹配5个字符第二个* 匹配0个字符
如果将*abc* 看做一个整体,那么在要让*abc与s中某一段相匹配,在后一个* 处枚举匹配0~多个,就可以将*abc* 能够匹配的所有情况列举出来。
因此时间复杂度为 o(n*m), 空间复杂度O(1)

而在正则匹配中由于存在多个可变长的匹配项,我们必须在每个可变长匹配项处回溯:

s:aaaccc
p:a*c*accc
此时必须枚举到a* 匹配2个a, c* 不匹配才能得到s与p匹配。

class Solution {
public:
    bool isMatch(string s, string p) {
        int star = -1;
        int ss = 0;
        int i =0;
        int j= 0;
        while(i< s.size())
        {
            if (j <p.size() && p[j]=='?' || p[j] ==s[i])
            {
                ++i; ++j; 
            }else if (j< p.size() && p[j] == '*')
            {
                star = j+1;// next
                ss = i; //0
                j = star;
            }else if (star >= 0)
            {
                j = star;
                i = ++ss;// 1...mulit
            }else
            {
                return false;
            }
        }
        while(j<p.size() && p[j]=='*') ++j;
        if (i==s.size()&& j==p.size())
            return true;
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值