问题
https://leetcode.com/problems/wildcard-matching/
解法一(DP)
时间复杂度O(n*m) 空间复杂度
2∗m
与正则匹配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;
}
};