- Wildcard Matching
https://leetcode.com/problems/wildcard-matching/description/
Difficulty:Hard
Total Accepted:148.7K
Total Submissions:680.8K
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 *.
Example 1:
Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.
Example 3:
Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Example 4:
Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 5:
Input:
s = "acdcb"
p = "a*c?b"
Output: false
算法一看就比较像可以用动态规划解决的问题,因为状态比较好划分而且状态与状态之间可以画图连线找关系,因此就决定用DP方式解决。
思考过程如下:
- 按照套路,用result[i][j]来存取p的前i个和s的前j个字符串的答案。
- 假设result[i][j]与相邻的result[i - 1][j - 1],result[i - 1][j]和result[i][j - 1]有某种神奇的关系。因此有必要先求result的第一行和第一列的初始值,毕竟后面的推导要用到这两排的数值。
- result的第一行除了第一个是true其他都是false, 很好理解,s的前i个(i>0)当然和空字符匹配不了。
- result的第一列,如果p[i]为*,则它与上一行的值相同。因为 *是自由变换的符号。否则初始为false。
- 那么其他行其他列呢?
- 可以看到,因为当p[i]为*时变换最为自由,所以只要result[i - 1][j - 1],result[i - 1][j]和result[i][j - 1]之中有一个为true那么result[i][j ]也为true。
- 如果p[i]==s[j]或者p[i]等于?,这意味着p和s的最后一个字符匹配,因此其结果result[i][j ]与result[i-1][j-1]是一样的,当做去掉s和p的最后一个字符考虑。
综上,就可以写出下面的程序了~
class Solution {
public:
bool isMatch(string s, string p) {
int resultX = p.length() + 1;
int resultY = s.length() + 1;
bool **result = new bool*[resultX];
for (int i = 0; i < resultX; i++) {
result[i] = new bool[resultY];
for (int j = 0; j < resultY; j++) {
result[i][j] = false;
}
}
//result[i][j]表示p前i个和s前j个是否匹配
//先初始化第一行除了第一个其他为false;
result[0][0] = true;
//先初始化第一列
for (int i = 1; i < resultX; i++) {
if (p[i - 1] == '*') {
result[i][0] = result[i-1][0];
}
}
for (int i = 1; i < resultX; i++) {
for (int j = 1; j < resultY; j++) {
if (s[j - 1] == p[i - 1]||p[i - 1] == '?') {//如果结尾相同或为?则看左上角对应的位置的值
result[i][j] = result[i-1][j-1];
}
else if(p[i-1]=='*'){//看左边,左斜上角和上边的值
if(result[i-1][j-1]==true||result[i-1][j]==true||result[i][j-1]==true){
result[i][j] = true;
}
}
}
}
return result[resultX-1][resultY-1];
}
};
static const auto io_sync_off = []()
{
// turn off sync
std::ios::sync_with_stdio(false);
// untie in/out streams
std::cin.tie(nullptr);
return nullptr;
}();