C++&Python 描述 LeetCode 10. 正则表达式匹配
Posted 亓官劼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++&Python 描述 LeetCode 10. 正则表达式匹配相关的知识,希望对你有一定的参考价值。
C++&Python 描述 LeetCode 10. 正则表达式匹配
大家好,我是亓官劼(qí guān jié ),在【亓官劼】公众号、CSDN、GitHub、B站、华为开发者论坛等平台分享一些技术博文。放弃不难,但坚持一定很酷!时光荏苒,未来可期,加油~
如果喜欢博主的文章可以关注博主的个人公众号【亓官劼】(qí guān jié),如果有需要找博主的话可以在公众号后台留言。建了个小交流群,Q群:545611263,要进微信群的话可以加我V:
qiguanjie2015
备注拉群即可。
《leetcode刷题系列》,博主将从第一题开始,每天更新当日的刷题情况,每题博主会尽量加一些解题思路的分析和C++&python代码的实现。每日在微信公众号【亓官劼】定时更新,有兴趣一起刷题的小伙伴可以关注公众号来一起卷起来呀。同时文章在GitHub中进行了开源,内含本系列文章目前已刷的各个题解和解题思路,GitHub地址为:LeetCode,如果文章对你有帮助的话可以来GitHub点个star,如果有更好的解题思路的话,也可以来GitHub提交~一起改进
题目
给你一个字符串 s
和一个字符规律 p
,请你来实现一个支持 '.'
和 '*'
的正则表达式匹配。
'.'
匹配任意单个字符'*'
匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s
的,而不是部分字符串。
示例 1:
输入:s = "aa" p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:s = "aa" p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:
输入:s = "ab" p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:s = "aab" p = "c*a*b"
输出:true
解释:因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:s = "mississippi" p = "mis*is*p*."
输出:false
提示:
0 <= s.length <= 20
0 <= p.length <= 30
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。- 保证每次出现字符
*
时,前面都匹配到有效的字符
解题思路
DP。由于*
和.
会导致两个串匹配的时候有多种可能性,因此这里可以采用动态规划来进行求解。
状态表示:f(i,j)
表示s
串中0~j
和p
串中0-j
的匹配情况。f(i,j) = true
表示匹配,f(i,j) = false
表示不匹配
状态转移:
p[j] != '*'
:f(i,j) = f(i-1,j-1) && ( (s[i] == p[j]) || (p[j] == '.') )
即在s[0 ~ i-1]
和p[0 ~ j-1]
匹配的情况下,如果s[i] == p[j]
或者p[j] == '.'
,则匹配。
p[j] == '*'
:f(i,j) = f(i,j-2) || ( f(i-1,j) && (s[i] == p[j-1] || p[j-1] == '.') )
即如果s[0 ~ i]
和p[0 ~ j-2]
匹配(当s[i]重复0次的情况
) 或者s[0 ~ i-1]
和p[ 0 ~ j]
匹配并且s[i] == p[j-1]
(当前一个字串可以匹配,当前重复之前的字符
)
算法实现 C++
class Solution {
public:
bool isMatch(string s, string p) {
int len1 = s.length(), len2 = p.length();
vector<vector<bool>> dp(len1+1, vector<bool> (len2+1, false));
// 在最开始加一个' ',方便解决边界问题
s = " " + s;
p = " " + p;
// 初始化
dp[0][0] = true;
for(int j = 2; j <= len2; j++)
if(p[j] == '*') dp[0][j] = dp[0][j-2];
for (int i = 1; i <= len1; i++)
for (int j = 1; j <= len2; j++) {
if(p[j] != '*'){
dp[i][j] = dp[i-1][j-1] && ( (s[i] == p[j]) || p[j] == '.');
}
if(p[j] == '*'){
if(j >= 2) dp[i][j] = dp[i][j - 2];
// 为了防止*复制的情况可以匹配但是被不复制的时候不匹配覆盖掉,所以dp[i][j]和自身进行一次或运算
if (s[i] == p[j - 1] || p[j - 1] == '.') dp[i][j] = dp[i-1][j] | dp[i][j];
}
}
return dp[len1][len2];
}
};
算法实现 python
class Solution:
def isMatch(self, s: str, p: str) -> bool:
n = s.__len__()
m = p.__len__()
dp = [ [False for j in range(m+1) ] for i in range(n+1) ]
# 在子串前面加一个' ',来方便解决边界问题
s = ' ' + s
p = ' ' + p
# init
dp[0][0] = True
for j in range(2, m+1):
if p[j] == '*': dp[0][j] = dp[0][j-2]
for i in range(1, n+1):
for j in range(1, m+1):
if p[j] != '*': dp[i][j] = dp[i-1][j-1] and ( s[i] == p[j] or p[j] == '.' )
if p[j] == '*':
if j >= 2: dp[i][j] = dp[i][j-2]
# 为了防止*复制的情况可以匹配但是被不复制的时候不匹配覆盖掉,所以dp[i][j]和自身进行一次或运算
if s[i] == p[j-1] or p[j-1] == '.': dp[i][j] = dp[i][j] or dp[i-1][j]
return dp[n][m]
以上是关于C++&Python 描述 LeetCode 10. 正则表达式匹配的主要内容,如果未能解决你的问题,请参考以下文章
C++&Python描述 LeetCode C++&Python描述 LeetCode 165. 比较版本号
C++&Python描述 LeetCode C++&Python描述 LeetCode 剑指 Offer 22. 链表中倒数第k个节点