0
点赞
收藏
分享

微信扫一扫

C++&Python 描述 LeetCode 10. 正则表达式匹配


C++&Python 描述 LeetCode 10. 正则表达式匹配

  大家好,我是亓官劼(qí guān jié ),在【亓官劼】公众号GitHub、B站、华为开发者论坛等平台分享一些技术博文。放弃不难,但坚持一定很酷!时光荏苒,未来可期,加油~

题目

给你一个字符串 ​​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]



举报

相关推荐

0 条评论