饭不食,水不饮,题必须刷
C语言免费动漫教程,和我一起打卡! 《光天化日学C语言》
LeetCode 太难?先看简单题! 《C语言入门100例》
数据结构难?不存在的! 《数据结构入门》
LeetCode 太简单?算法学起来! 《夜深人静写算法》
究极算法奥义!深度学习! 《深度学习100例》
给定一个 匹配字符串 s (只包含小写字母) 和一个 模式字符串 p (包含小写字母和两种额外字符:
'.'
和'*'
),要求实现一个支持'.'
和'*'
的正则表达式匹配('*'
前面保证有字符)。
'.'
匹配任意单个字符
'*'
匹配零个或多个前面的那一个元素
样例输入:s = "mississippi"
、p = "mis*is*p*."
样例输出:false
。
class Solution {
public:
bool isMatch(string str, string pattern) {
}
};
str
是匹配串;pattern
是模式串;LeetCode 10. 正则表达式匹配
于是,对模式串进行分情况讨论:
1)当 p[j] 为.
时,代表 s[i] 为任意字符时,它都能够匹配(没毛病吧?没毛病),所以问题就转化成了求 匹配串前缀 s[0:i-1] 和 模式串前缀 p[0:j-1] 是否有匹配的问题,也就是这种情况下 f ( i , j ) = f ( i − 1 , j − 1 ) f(i, j) = f(i-1, j-1) f(i,j)=f(i−1,j−1),如图1所示:
图1
2)当 p[j] 为*
时,由于*
前面保证有字符,所以拿到字符 p[j-1],分情况讨论:
2.a)如果 p[j-1] 为.
时,可以匹配所有 s[0:i] 的后缀,这种情况下,只要 f ( k , j − 2 ) f(k, j-2) f(k,j−2) 为 1, f ( i , j ) f(i, j) f(i,j) 就为 1;其中 k ∈ [ 0 , i ] k \in [0, i] k∈[0,i]。如图2所示:
图2
2.b)如果 p[j-1] 非.
时,只有当 s[0:i] 的后缀 字符全为 p[j-1] 时,才能去匹配 s[0:i] 的前缀,同样转化成 f ( k , j − 2 ) f(k, j-2) f(k,j−2) 的子问题。如图3所示:
图3
3)当 p[j] 为其他任意字符时,一旦 p[j] 和 s[i] 不匹配,就认为 f ( i , j ) = 0 f(i, j) = 0 f(i,j)=0,否则 f ( i , j ) = f ( i − 1 , j − 1 ) f(i, j) = f(i-1, j-1) f(i,j)=f(i−1,j−1),如图4所示:
图4
const int maxn = 110;
class Solution {
public:
int dfs(int dp[maxn][maxn], string& str, string& pattern, int sidx, int pidx) {
if(sidx == -1 && pidx == -1) // (1)
return 1;
if(pidx == -1) // (2)
return 0;
if(sidx == -2) { // (3)
return 0;
}
int &x = dp[sidx+1][pidx+1]; // (4)
if(x != -1)
return x; // (5)
x = 0; // (6)
if(pattern[pidx] == '.') {
x |= dfs(dp, str, pattern, sidx-1, pidx-1); // (7)
}else if(pattern[pidx] == '*') {
if(pidx == 0) {
x |= dfs(dp, str, pattern, sidx, pidx-1);
}else {
char c = pattern[pidx-1];
x |= dfs(dp, str, pattern, sidx, pidx-2); // (8)
for(int i = sidx; i >= 0; --i) {
if(c == '.' || c == str[i]) { // (9)
x |= dfs(dp, str, pattern, i - 1, pidx - 2);
}else {
break;
}
}
}
}else {
if(sidx >= 0 && pattern[pidx] == str[sidx]) // (10)
x |= dfs(dp, str, pattern, sidx-1, pidx-1);
else // (11)
x = 0;
}
return x;
}
bool isMatch(string str, string pattern) {
int dp[maxn][maxn];
int len = str.size();
int plen = pattern.size();
memset(dp, -1, sizeof(dp));
int ans = dfs(dp, str, pattern, len-1, plen-1);
return ans;
}
};
1
;0
;0
;.
表示匹配任意单个字符,对应上文 1)的情况;c*
去匹配空串,剩下的进行匹配;.
或者 匹配字符 和 模式字符 相等,都能够进行下一步匹配;对应上文 2)的情况;两个串的模式匹配问题,可以采用动态规划求解,实现方式可以采用记忆化搜索,更加好理解。这题对于求职来说较难,如果在面试的遇到,那表明你运气不好哈(当然,不排除你是 ACM 大神!Good Luck!)。