题目
//给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
//
// '?' 可以匹配任何单个字符。
//'*' 可以匹配任意字符串(包括空字符串)。
//
//
// 两个字符串完全匹配才算匹配成功。
//
// 说明:
//
//
// 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 = "*a*b"
//输出: true
//解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
//
//
// 示例 5:
//
// 输入:
//s = "acdcb"
//p = "a*c?b"
//输出: false
// Related Topics 贪心算法 字符串 动态规划 回溯算法
思路
画出dp[i][j]因为本题空字符串也算一种情况则0位为空
dp[i][j]表示在当前字符串i的情况下j在那一个位置是否是匹配的
因为字符串不可能回退的原因,所以在表格中应当只能右或者往右下走[即i一直在增加]
则其他格子一律当F
s = “acdcb”
p = “a*d?b”
为例
如果都为空串则为空
空 | a | c | d | c | b | |
---|---|---|---|---|---|---|
空 | T | |||||
a | ||||||
* | ||||||
d | ||||||
? | ||||||
b |
往下则是s="" p="a"所以是F
空 | a | c | d | c | b | |
---|---|---|---|---|---|---|
空 | T | |||||
a | F | T | ||||
* | ||||||
d | ||||||
? | ||||||
b |
遇到*则为特殊符号处理,匹配后面所有字符串即下面到到右边全是T
空 | a | c | d | c | b | |
---|---|---|---|---|---|---|
空 | T | |||||
a | F | T | ||||
* | T | T | T | T | T | |
d | ||||||
? | ||||||
b |
遇到*则为特殊符号处理,匹配后面所有字符串即下面到到右边全是T
空 | a | c | d | c | b | |
---|---|---|---|---|---|---|
空 | T | |||||
a | F | T | ||||
* | T | T | T | T | T | |
d | T | |||||
? | T | |||||
b | T |
遇到?则为特殊符号处理,匹配后面所有字符串即右下必为T
空 | a | c | d | c | b | |
---|---|---|---|---|---|---|
空 | T | |||||
a | F | T | ||||
* | T | T | T | T | ||
d | T | |||||
? | T | |||||
b | T |
根据推演则可得到
当s[i] == p[j]的时候即为T
当p[j] == ?的时候即为T
当p[j] == * 的时候即为T
但是dp[i][j]表示为当前字符串在在i长度的时候j的匹配规则是否符合
所以不能单纯的从当前一个来判断,应当根据前面的状态来推导下面的[如果前面是F则右下应该都是F]
所以可以推导得出
如果p[j]不是特殊符号 则 s[i] == p[j] 或者jp[j]是’?'号的 的时候 取值应当和左上角一致即
if (dp[i][j] = (sC[i-1] == p[i-1])) {
dp[i][j] = dp[i-1][j-1];
}
如果p[j]是’'则取值应当是
if(p[i-1] == '’){
dp[i][j] = dp[i][j - 1] || >dp[i - 1][j];
}
为什么会这样,这里有2个情况,两者满足任何一种情况都满足
1.使用
> 必定和当前格子左边一致[即视当前s[i]为空串]
2.不使用
> 必定和当前格子上面一致[即视j[i]为空串]
3.特殊情况
以N个’'开头且字符串为空
所以优先初始化将以开头的全部设置为T,然后根据使用原则就可以抛弃所有以*开头不符合条件的数据
答案
class Solution {
public boolean isMatch(String s, String p) {
// dp[i][j] 表示当前长度i和当前长度j在当前模式是否匹配
char[] sC = s.toCharArray();
char[] pC = p.toCharArray();
int n = sC.length;
int m = pC.length;
boolean[][] dp = new boolean[n+1][m+1];
dp[0][0] = true;
// 处理以*开头的
for(int i = 1;i<=pC.length;i++){
if(p.charAt(i-1) == '*'){
dp[0][i] = true;
continue;
}
break;
}
// i 代表待匹配字符串
// j 代表匹配模式
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
char c = p.charAt(j - 1);
if(c == '*'){
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
continue;
}
// 如果当前等于?则取决于上一次匹配是否正确
if(c == '?'){
dp[i][j] = dp[i-1][j-1];
continue;
}
// 如果当前不等于*或者?则当前等于当前的值是否相等
if (dp[i][j] = (sC[i-1] == c)) {
dp[i][j] = dp[i-1][j-1];
}
}
}
return dp[n][m];
}
}