版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26440803/article/details/80686141
这个道题的大意是:输入一个目标串:s ,以及一个匹配串:p,进行如下规则的匹配:
如果p中存在?,则可以匹配s中任意一个单个字符
如果p中存在*,则可以匹配s中任意一串连续的序列,包括空字符
解法一:双指针
给定两个指针
pIndex,sIndex
。一个遍历p一个遍历s。当我们遍历时,会遇见如下的情况:
- 当s[pIndex] == s[sIndex] 或者 p[Index] == ‘?’ 时,我们可以直接对pIndex,sIndex 进行前移位操作。
- 如果当p[pIndex] ==
'*'
时,我们需要做如下操作:pIndex向后移位,重复(1)操作,因为我们的*有可能匹配的是空,当然,我们还需要记录下这个pIndex位置与匹配s串中失败的那个位置点match ,因为我们不知道当前位置的*
匹配是否是正确的,因为当*
只有后面一位与s进行匹配成功,而其他的不匹配则说明我们的*
匹配s串的位置不对(即使这里*
后面一位与上面的s匹配成功)。 - 当操作2失败后,我们应该回溯,通过上面记录的
*
的位置,我们从*
下一个位置与match 下一个位置继续进行(1)操作。 - 判断pIndex 是否走完。
public static boolean isMatch(String str,String pattern) {
int s = 0, p = 0,match = 0,startIdx = -1;
while(s<str.length()) {
if(p<pattern.length() && (pattern.charAt(p) == '?' || str.charAt(s) == pattern.charAt(p))) {
s++;p++;
}else if(p<pattern.length() && pattern.charAt(p) == '*') {
startIdx = p;
match = s;
p++;
}else if(startIdx != -1) {
p = startIdx +1;
match++;
s = match;
}else {
return false;
}
}
while(p < pattern.length() && pattern.charAt(p) == '*') {
p++;
}
return p == pattern.length();
}
解法二:DP
通过分析可以得出如下的递归关系公式:
这里的i,j分别代表s中的j位置与p中的i位置是否匹配。利用DP,我们可以将问题的规模不断缩小、。
如果当pattern.charAt(j-1) == str.charAt(i-1) || pattern.charAt(j-1) == '?'
那么证明s[j] == p[i],我们只需要关心s[i-1] == s[j-1]就可以了。成功将问题规模缩小。
如果当p[i]=='*'
,'*'
匹配0个字符,dp[i][j]=dp[i-1][j]
;匹配1个字符,dp[i][j]=dp[i-1][j-1]所以,
dp[i][j]=dp[i-1][j]||dp[i-1][j-1]||……||dp[i-1][0]
。
但是上面的公式可以化简,当p.charAt(i)=='*'
时,有
dp[i][j-1]=dp[i-1][j-1]||dp[i-1][j-2]||……||dp[i-1][0]
成功转换为:
dp[i][j] = dp[i-1][j] || dp[i][j-1]
.
public static boolean isMatchDP(String str,String pattern) {
int sLen = str.length();
int lLen = pattern.length();
boolean[][] dp = new boolean[sLen+1][lLen+1];
dp[0][0] = true;
for(int i=1;i<=lLen;i++) {
dp[0][i] = dp[0][i-1] && pattern.charAt(i-1) == '*';
}
for(int i=1; i<= sLen;i++) {
for(int j=1; j <= lLen ;j++) {
if(pattern.charAt(j-1) == str.charAt(i-1) || pattern.charAt(j-1) == '?') {
dp[i][j] = dp[i-1][j-1];
}else if(pattern.charAt(j-1) == '*'){
dp[i][j] = dp[i-1][j] || dp[i][j-1];
}
}
}
return dp[sLen][lLen];
}