当前位置: 面试刷题>> 通配符匹配 (经典算法题500道)
### 题目描述
**通配符匹配** 问题是一种字符串匹配问题,其中模式字符串可以包含两种特殊字符:
- `?`:表示可以匹配任何单个字符。
- `*`:表示可以匹配零个或多个前面的那一个元素(注意是前面的那一个元素,不是前面的所有元素)。
给定一个字符串 `s` 和一个模式字符串 `p`,实现一个函数来判断 `s` 是否能够和 `p` 匹配。
### 示例
**示例 1**:
```
输入: s = "aa", p = "a*"
输出: true
解释: '*' 表示零个或多个 'a'。因此,'aa' 可以被 'a*' 匹配。
```
**示例 2**:
```
输入: s = "ab", p = ".*"
输出: true
解释: '.*' 表示首先匹配任意单个字符('a'),然后匹配零个或多个任意字符('b')。
```
**示例 3**:
```
输入: s = "aab", p = "c*a*b"
输出: false
解释: 'c*' 不能匹配 'aab' 的任何部分。
```
### 解题思路
该问题可以使用动态规划(Dynamic Programming)来解决。我们定义一个二维数组 `dp[i][j]`,其中 `dp[i][j]` 表示字符串 `s` 的前 `i` 个字符和模式 `p` 的前 `j` 个字符是否匹配。
1. 初始化 `dp[0][0] = True`,表示两个空字符串是匹配的。
2. 如果 `p` 的第 `j` 个字符是 `*`,则 `dp[i][j]` 可以由 `dp[i][j-1]` 或 `dp[i-1][j]`(且 `s[i-1] == p[j-1]` 或 `p[j-1]` 是 `?`)推导出来。
3. 如果 `p` 的第 `j` 个字符不是 `*`,则 `dp[i][j]` 为真当且仅当 `i > 0` 且 (`s[i-1] == p[j-1]` 或 `p[j-1]` 是 `?`),并且 `dp[i-1][j-1]` 为真。
### PHP 代码示例
```php
function isMatch($s, $p) {
$m = strlen($s);
$n = strlen($p);
$dp = array_fill(0, $m + 1, array_fill(0, $n + 1, false));
$dp[0][0] = true;
for ($j = 1; $j <= $n; $j++) {
if ($p[$j - 1] == '*') {
$dp[0][$j] = $dp[0][$j - 1];
}
}
for ($i = 1; $i <= $m; $i++) {
for ($j = 1; $j <= $n; $j++) {
if ($p[$j - 1] == '*') {
$dp[$i][$j] = $dp[$i][$j - 1] || ($dp[$i - 1][$j] && ($s[$i - 1] == $p[$j - 2] || $p[$j - 2] == '?'));
} elseif ($s[$i - 1] == $p[$j - 1] || $p[$j - 1] == '?') {
$dp[$i][$j] = $dp[$i - 1][$j - 1];
}
}
}
return $dp[$m][$n];
}
```
### Python 代码示例
```python
def isMatch(s, p):
m, n = len(s), len(p)
dp = [[False] * (n + 1) for _ in range(m + 1)]
dp[0][0] = True
for j in range(1, n + 1):
if p[j - 1] == '*':
dp[0][j] = dp[0][j - 1]
for i in range(1, m + 1):
for j in range(1, n + 1):
if p[j - 1] == '*':
dp[i][j] = dp[i][j - 1] or (dp[i - 1][j] and (s[i - 1] == p[j - 2] or p[j - 2] == '?'))
elif s[i - 1] == p[j - 1] or p[j - 1] == '?':
dp[i][j] = dp[i - 1][j - 1]
return dp[m][n]
```
### JavaScript 代码示例
```javascript
function isMatch(s, p) {
const m = s.length;
const n = p.length;
const dp = Array.from({length: m + 1}, () => Array(n + 1).fill(false));
dp[0][0] = true;
for (let j = 1; j <= n; j++) {
if (p[j - 1] === '*') {
dp[0][j] = dp[0][j - 1];
}
}
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (p[j - 1] === '*') {
dp[i][j] = dp[i][j - 1] || (dp[i - 1][j] && (s[i - 1] === p[j - 2] || p[j - 2] === '?'));
} else if (s[i - 1] === p[j - 1] || p[j - 1] === '?') {
dp[i][j] = dp[i - 1][j - 1];
}
}
}
return dp[m][n];
}
```
**码小课**网站中有更多相关内容分享给大家学习,包括但不限于算法、数据结构、面试技巧等,欢迎大家访问学习。