Leetcode 44. Wildcard Matching
44. Wildcard Matching
题目链接:https://leetcode.com/problems/wildcard-matching/
Description:
Given an input string (s
) and a pattern (p
), 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).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like?
or*
.
Example 1:
Input: s = "adceb" p = "*a*b" Output: true Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 2:
Input: s = "acdcb" p = "a*c?b" Output: false
题意:
给出两个字符串,一个是匹配串,另一个是用来匹配的串,其中*代表任意的数,包括无数;"?"代表任意的一个字符。
现在问两个串是否能够成功匹配。
题解:
这题dp应该还是好做,dp[i,j]含义为第一个串匹配前i个,第二个串匹配前j个是否能够成功匹配。
初始化为dp[0,0]=1,然后转移方程为:
dp[i,j]=dp[i-1,j-1] && s[i-1]==p[j-1] || p[j-1]=="?" ; if(p[j-1]=="*") dp[i,j]=dp[i-1,j] || dp[i,j-1] || dp[i-1,j-1]。
对第二个式子解释一下吧,如果当前的p是"*",那么当前状态可能就由三种情况转移过来:
1."*"匹配了第i-1个字符,现在继续匹配第i个;2."*"不匹配,即当做空;3."*"作为开头来匹配第i个字符。
然后就可以做了,代码如下:
class Solution { public: bool isMatch(string s, string p) { int n = s.length(), m = p.length(); int dp[n+5][m+5]; memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=m;i++){ if(p[i-1]=='*'){ dp[0][i]=1; continue ; } break ; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ dp[i][j]=(dp[i-1][j-1]&&(s[i-1]==p[j-1] || p[j-1]=='?')); if(p[j-1]=='*') dp[i][j]=(dp[i-1][j]||dp[i][j-1]||dp[i-1][j-1]); } } return dp[n][m]; } };
但是这里dp的复杂度是O(n^2),复杂度有点高,我们可以换一种思路来解,即指针法。
这个方法有点巧妙,类似于模拟,即定义两个i,j指针,分别在两个字符串中,现在同样有几种情况:
假设当前s[i-1]==p[j-1] || p[j-1]=="?",意即能够重新匹配,我们i++,j++;
还有一种情况就是当前的p[j-1]=="*",那么我们记录下i当前的位置,以及让j++,继续匹配。
如果出现匹配不成功的情况,那么就让j回到刚才记录的"*"之后那一位,否则无解;让i回到刚才记录i的位置的下一位继续匹配。
就不断重复这样的匹配操作,如果再一次遇到一个"*",那么我们就更换"*"的位置,采用最近的"*",这是最优的,因为这里的"*"可以看作空,也就是说既可以从之前那里匹配过来,也可以从当前这里开始匹配,这样时间复杂度会小些,不然又O(n^2)了。
以上就是该算法的大体思想,另外注意一下代码的实现,最后的时候要记得看是否两个指针都到了末尾,这样才算匹配成功。
注意一下代码的细节,建议亲自实现。
代码如下:
class Solution { public: bool isMatch(string s, string p) { int n = s.length(), m = p.length(); int i=0,j=0; int pre=-1,alp=-1; while(i<n){ if(j<m&&(s[i]==p[j]||p[j]=='?')) i++,j++; else if(j<m&&p[j]=='*'){ pre = j++; alp = i; }else if(pre>-1){ j = pre+1; i = ++alp; }else return false ; } while(j<m && p[j]=='*') j++; return j==m; } };
重要的是自信,一旦有了自信,人就会赢得一切。