# 【線性 dp】A016_LC_通配符匹配（分類討論）

## 一、Problem

Given an input string (s) and a pattern §, 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 letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like ? or *.

Input:
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Input:
s = "acdcb"
p = "a*c?b"
Output: false

## 二、Solution

### 方法一：dp

• 定義狀態
• $f[i][j]$ 表示 s 的前 $i$ 個字符能否用 p 的前 $j$ 個字符進行匹配，這樣比較好理解
• 思考初始化：
• $f[0][0] = true$
• $f[0][j] = (f[0][j-1]\ and\ p[j-1] == *)$，當 s 爲空串時，p 的前 $j$ 個字符只有是 * 號時，才能用 p 進行匹配；? 不行是因爲 ? 只能匹配單個字符
• 思考狀態轉移方程
• 如果 $s[i] = p[j]$ 或者 $s[i] \not= p[j]$$p[j] =\ ?$，則有 $f[i][j] = f[i-1][j-1]$
• 如果 $s[i] \not= p[j]，p[j] = *$ ，則 * 有兩種作用：
• 當做空串進行匹配（ac, ac*），$f[i][j] = f[i][j-1]$
• 當做有意義的字符串（acac, ac*)，由上可得，因爲 $f[3][3] = true$，所以 $f[i][j] = f[i-1][j]$
• 綜上，$f[i][j] = f[i][j-1]\ ||\ f[i-1][j]$
• 思考輸出$f[n][m]$
class Solution {
public:
bool isMatch(string s, string p) {
int n = s.size(), m = p.size();
vector<vector<bool>> f(n+1, vector<bool>(m+1));  f[0][0] = true;
for (int j = 1; j <= m; j++) if (p[j-1] == '*') {
f[0][j] = f[0][j-1];
}

for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (s[i-1] == p[j-1] || p[j-1] == '?') {
f[i][j] = f[i-1][j-1];
} else if (p[j-1] == '*') {
f[i][j] = f[i][j-1] || f[i-1][j];
}
}
return f[n][m];
}
};

• 時間複雜度：$O(n × m)$
• 空間複雜度：$O(n × m)$