LeeCode(动态规则,贪心算法)44_通配符匹配
题目:
给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。
‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:
s = “aa”
p = ""
输出: true
解释: '’ 可以匹配任意字符串。
示例 3:
输入:
s = “cb”
p = “?a”
输出: false
解释: ‘?’ 可以匹配 ‘c’, 但第二个 ‘a’ 无法匹配 ‘b’。
示例 4:
输入:
s = “adceb”
p = “ab”
输出: true
解释: 第一个 ‘’ 可以匹配空字符串, 第二个 '’ 可以匹配字符串 “dce”.
示例 5:
输入:
s = “acdcb”
p = “a*c?b”
输出: false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/wildcard-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
方法一:
动态规划
- 创建一个dp[][]保存所有的匹配情况,用dp[i][j]表示s的前i个字符和p的前j个字符是否匹配。
- 匹配情况大致分为三种:
1.si=pi
2.pi为?号
3.pi为*号
整合后的状态转移方程:
确定边界:
-
dp[0][0]=True,即当字符串 s 和模式 p 均为空时,匹配成功;
-
dp[i][0]=False,即空模式无法匹配非空字符串;
-
dp[0][j] 需要分情况讨论:因为星号才能匹配空字符串,所以只有当模式 p 的前 j 个字符均为星号时,dp[0][j] 才为真。
Java代码:
public class 通配符匹配 {
public boolean isMatch(String s,String p){
int m = s.length();
int n = p.length();
boolean[][] dp = new boolean[m+1][n+1];
dp[0][0] =true;
for(int i=1;i<=n;i++){
if(p.charAt(i-1)=='*'){
dp[0][i]=true;
}else{
break;
}
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(p.charAt(j-1)=='*'){
dp[i][j]=dp[i-1][j] || dp[i][j-1];
}else if(p.charAt(j-1)=='?' || p.charAt(j-1)==s.charAt(i-1)){
dp[i][j] = dp[i - 1][j - 1];
}
}
}
return dp[m][n];
}
}
方法二:
贪心算法
-
因为可以匹配一个或多个字符所有n个和1个*实际上是等价的。 所有我们可以把p看成p=∗ u1∗u2∗u3∗u4∗u5∗u6∗
-
算法的本质是首先在s中找到u1然后依次找到u2,u3…
此外还有两种情况:
- 模式 p 的开头字符不是星号;
- 模式 p 的结尾字符不是星号。
第二种情况处理起来并不复杂。如果模式 p 的结尾字符不是星号,那么就必须与字符串 s 的结尾字符匹配。那么我们不断地匹配 s 和 p 的结尾字符,直到 p 为空或者 p 的结尾字符是星号为止。在这个过程中,如果匹配失败,或者最后 p 为空但 s 不为空,那么需要返回 False。
第一种情况的处理也很类似,我们可以不断地匹配 s 和 p 的开头字符。下面的代码中给出了另一种处理方法,即修改 sRecord 和 tRecord 的初始值为 −1,表示模式 p 的开头字符不是星号,并且在匹配失败时进行判断,如果它们的值仍然为 −1,说明没有「反悔」重新进行匹配的机会。
Java代码:
public class 通配符匹配 {
public boolean isMatch(String s, String p) {
int sRight = s.length();
int pRight = p.length();
//不是以*号结尾
while(sRight>0 && pRight>0 && p.charAt(pRight-1)!='*'){
if(charMatch(s.charAt(sRight-1),p.charAt(pRight-1))){
--sRight;
--pRight;
}else{
return false;
}
}
if(pRight==0){
return sRight==0;
}
int sIndex=0,pIndex=0;
int sRecord=-1,pRecord=-1;
while(sIndex<sRight && pIndex<pRight){
if(p.charAt(pIndex)=='*'){
++pIndex;
sRecord=sIndex;
pRecord=pIndex;
}else if(charMatch(s.charAt(sIndex),p.charAt(pIndex))){
++pIndex;
++sIndex;
}else if(sRecord!=-1 && sRecord+1 < sRight){
++sRecord;
sIndex = sRecord;
pIndex = pRecord;
}else{
return false;
}
}
return allStars(p,pIndex,pRight);
}
public boolean allStars(String str, int left, int right) {
for(int i=left;i<right;i++){
if(str.charAt(i)!='*'){
return false;
}
}
return true;
}
public boolean charMatch(char u, char v) {
return u==v || u=='?';
}
}