Hard!

题目描述:

给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。

  1. '.' 匹配任意单个字符。
  2. '*' 匹配零个或多个前面的元素。

匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

说明:

  • s 可能为空,且只包含从 a-z 的小写字母。
  • p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *

示例 1:

  1. 输入:
  2. s = "aa"
  3. p = "a"
  4. 输出: false
  5. 解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

  1. 输入:
  2. s = "aa"
  3. p = "a*"
  4. 输出: true
  5. 解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"

示例 3:

  1. 输入:
  2. s = "ab"
  3. p = ".*"
  4. 输出: true
  5. 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。

示例 4:

  1. 输入:
  2. s = "aab"
  3. p = "c*a*b"
  4. 输出: true
  5. 解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"

示例 5:

  1. 输入:
  2. s = "mississippi"
  3. p = "mis*is*p*."
  4. 输出: false

解题思路:

这道题分的情况的要复杂一些,需要用递归Recursion来解:

- 若p为空,且s也为空,返回true,反之返回false

- 若p的长度为1,且s长度也为1,且相同或是p为'.'则返回true,反之返回false

- 若p的第二个字符不为*,且此时s为空则返回false,否则判断首字符是否匹配,且从各自的第二个字符开始调用递归函数匹配

- 若p的第二个字符为*,s不为空且字符匹配,调用递归函数匹配s和去掉前两个字符的p,若匹配返回true,否则s去掉首字母

- 返回调用递归函数匹配s和去掉前两个字符的p的结果

C++参考答案一:

  1. class Solution {
  2. public:
  3. bool isMatch(string s, string p) {
  4. if (p.empty()) return s.empty();
  5. if (p.size() == ) {
  6. return (s.size() == && (s[] == p[] || p[] == '.'));
  7. }
  8. if (p[] != '*') {
  9. if (s.empty()) return false;
  10. return (s[] == p[] || p[] == '.') && isMatch(s.substr(), p.substr());
  11. }
  12. while (!s.empty() && (s[] == p[] || p[] == '.')) {
  13. if (isMatch(s, p.substr())) return true;
  14. s = s.substr();
  15. }
  16. return isMatch(s, p.substr());
  17. }
  18. };

上面的方法可以写的更加简洁一些,但是整个思路还是一样的,我们先来判断p是否为空,若为空则根据s的为空的情况返回结果。当p的第二个字符为*号时,由于*号前面的字符的个数可以任意,可以为0,那么我们先用递归来调用为0的情况,就是直接把这两个字符去掉再比较,或者当s不为空,且第一个字符和p的第一个字符相同时,我们再对去掉首字符的s和p调用递归,注意p不能去掉首字符,因为*号前面的字符可以有无限个;如果第二个字符不为*号,那么我们就老老实实的比较第一个字符,然后对后面的字符串调用递归,参见代码如下:

C++参考答案二:

  1. class Solution {
  2. public:
  3. bool isMatch(string s, string p) {
  4. if (p.empty()) return s.empty();
  5. if (p.size() > && p[] == '*') {
  6. return isMatch(s, p.substr()) || (!s.empty() && (s[] == p[] || p[] == '.') && isMatch(s.substr(), p));
  7. } else {
  8. return !s.empty() && (s[] == p[] || p[] == '.') && isMatch(s.substr(), p.substr());
  9. }
  10. }
  11. };

我们也可以用DP来解,定义一个二维的DP数组,其中dp[i][j]表示s[0,i)和p[0,j)是否match,然后有下面三种情况(下面部分摘自:https://leetcode.com/problems/regular-expression-matching/discuss/5684/9-lines-16ms-c-dp-solutions-with-explanations):

1.  P[i][j] = P[i - 1][j - 1], if p[j - 1] != '*' && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
2.  P[i][j] = P[i][j - 2], if p[j - 1] == '*' and the pattern repeats for 0 times;
3.  P[i][j] = P[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'), if p[j - 1] == '*' and the pattern repeats for at least 1 times.

  1. class Solution {
  2. public:
  3. bool isMatch(string s, string p) {
  4. int m = s.size(), n = p.size();
  5. vector<vector<bool>> dp(m + , vector<bool>(n + , false));
  6. dp[][] = true;
  7. for (int i = ; i <= m; ++i) {
  8. for (int j = ; j <= n; ++j) {
  9. if (j > && p[j - ] == '*') {
  10. dp[i][j] = dp[i][j - ] || (i > && (s[i - ] == p[j - ] || p[j - ] == '.') && dp[i - ][j]);
  11. } else {
  12. dp[i][j] = i > && dp[i - ][j - ] && (s[i - ] == p[j - ] || p[j - ] == '.');
  13. }
  14. }
  15. }
  16. return dp[m][n];
  17. }
  18. };

LeetCode(10):正则表达式匹配的更多相关文章

  1. Leetcode 10. 正则表达式匹配 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  2. Java实现 LeetCode 10 正则表达式匹配

    10. 正则表达式匹配 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符 '*' 匹配零个或多个前面的那一个元素 所谓匹配, ...

  3. [LeetCode] 10. 正则表达式匹配

    题目链接:https://leetcode-cn.com/problems/regular-expression-matching/ 题目描述: 给定一个字符串 (s) 和一个字符模式 (p).实现支 ...

  4. LeetCode 10. 正则表达式匹配(Regular Expression Matching)

    题目描述 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或多个前面的元素. 匹配应该覆盖整个字符串 (s ...

  5. LeetCode 10——正则表达式匹配

    1. 题目 2. 解答 在 回溯算法 中我们介绍了一种递归的思路来求解这个问题. 此外,这个问题也可以用动态规划的思路来解决.我们定义状态 \(P[i][j]\) 为子串 \(s[0, i)\) 和 ...

  6. leetcode题目10.正则表达式匹配(困难)

    题目描述: 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个  ...

  7. 【LeetCode】正则表达式匹配(动态规划)

    题目描述 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或多个前面的元素. 匹配应该覆盖整个字符串 (s ...

  8. LeetCode10. 正则表达式匹配

    10. 正则表达式匹配 描述 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或多个前面的元素. 匹配应该 ...

  9. leetcode 10 Regular Expression Matching(简单正则表达式匹配)

    最近代码写的少了,而leetcode一直想做一个python,c/c++解题报告的专题,c/c++一直是我非常喜欢的,c语言编程练习的重要性体现在linux内核编程以及一些大公司算法上机的要求,pyt ...

  10. Leetcode(10)正则表达式匹配

    Leetcode(10)正则表达式匹配 [题目表述]: 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或 ...

随机推荐

  1. [转帖] Linux 创建一个简单的私有CA、发证、吊销证书

    原创帖子地址:   https://blog.csdn.net/mr_rsq/article/details/71001810 Linux 创建一个简单的私有CA.发证.吊销证书 2017年04月30 ...

  2. CentOS下搭建Hive

    目录 下载解压hive mysql驱动 配置文件 hive-env.sh hive-site.xml 首次启动hive 使用schemaTool初始化mysql数据库 错误总结 警告汇总 参考:htt ...

  3. iOS 给UIView添加xib

    2017-08-25编辑:这文章有点过时了 推荐新的文章:http://www.cnblogs.com/hero11223/p/6881848.html 一段时间没敲代码,以前一些简单的都不会做了,翻 ...

  4. 【题解】Friends

    题目描述 有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将其复制一遍得到T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在你得到了U,请你找出S. 输入输出格式 输入格式 第一行,一 ...

  5. BZOJ4066 简单题(KD-Tree)

    板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...

  6. P3254 圆桌问题

    题目链接 非常简单的一道网络流题 我们发现每个单位的人要坐到不同餐桌上,那也就是说每张餐桌上不能有同一单位的人.这样的话,我们对于每个单位向每张餐桌连一条边权为1的边,表示同一餐桌不得有相同单位的人. ...

  7. oracle 查看临时表空间temp 的使用情况以及扩展表空间

    SELECT D.TABLESPACE_NAME,SPACE "SUM_SPACE(M)",BLOCKS SUM_BLOCKS, USED_SPACE )/SPACE*,) &qu ...

  8. 洛谷P3380 【模板】二逼平衡树(树套树,树状数组,线段树)

    洛谷题目传送门 emm...题目名写了个平衡树,但是这道题的理论复杂度最优解应该还是树状数组套值域线段树吧. 就像dynamic ranking那样(蒟蒻的Sol,放一个link骗访问量233) 所有 ...

  9. 【Treap 例题】神秘岛(island)

    神秘岛(island) 题目描述: 除了敲代码和撩妹,旅行是cxw123 的第三爱好.他来到了澳大利亚东北部的大宝礁,在这里,有一个隔绝人世的神秘岛,这个岛不同于附近其他的珊瑚岛,它的生长速度极快,甚 ...

  10. luogu1373 小a和uim之大逃离 (dp)

    直接设f[i][j][k][l][2]是在(i,j)时两人分数是k,l,复杂度会爆掉 但其实只需要知道两人分数只差就行了 所以设f[i][j][k][2],k是分数之差%(K+1),最后一位表示该谁走 ...