Implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). The function prototype should be:
bool isMatch(const char *s, const char *p) Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true

解法1:

  这道题中的*表示*之前的那个字符可以有0个,1个或是多个,就是说,字符串a*b,可以表示b或是aaab,即a的个数任意;字符串.*b,可以表示b或是xyzb。需要用递归Recursion来解,大概思路如下:(原字符串为s,正则式为p)

  - 若p为空:

    • 若s也为空,返回true,反之返回false

  - 若p的长度为1:

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

  - 若p的第二个字符不为*:

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

  - 若p的第二个字符为*:

    • 若s不为空且字符匹配,调用递归函数匹配s和去掉前两个字符的p,若匹配返回true,否则s去掉首字母
    • 否则,返回调用递归函数匹配s和去掉前两个字符的p的结果
public class Solution {
public boolean isMatch(String s, String p) {
if (p.isEmpty()) {
if (s.isEmpty()) return true;
return false;
} if (p.length() == 1)
return (s.length() == 1 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')); if (p.charAt(1) != '*')
return (s.length() > 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && isMatch(s.substring(1), p.substring(1))); while (!s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')) {
if (isMatch(s, p.substring(2))) return true;
s = s.substring(1);
}
return isMatch(s, p.substring(2));
}
}

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

public class Solution {
public boolean isMatch(String s, String p) {
if (p.isEmpty()) {
if (s.isEmpty()) return true;
return false;
} if (p.length() > 1 && p.charAt(1) == '*')
return (isMatch(s, p.substring(2)) || (!s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && isMatch(s.substring(1), p))); return (!s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && isMatch(s.substring(1), p.substring(1)));
}
}

解法2:

  用动态规划DP来解,用二维数组 dp[i][j] 表示s的前i个字符s[0,i) 和p的前j个字符p[0,j)是否匹配,分以下几种情况:

  • 当前字符 p[j-1]=='*' 时,*前的字符可能不出现或者至少出现一次,即:
dp[i][j] = dp[i][j - 2] || (i > 0 && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.') && dp[i - 1][j]);
    • dp[i][j - 2] 表示*前的字符一次都不出现,即与 s[0,i)和p[0,j-2) 的匹配情况相同;
    • i > 0 && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.') && dp[i - 1][j] 表示*前的字符至少出现一次,即与 s[0,i-1)和p[0,j)de匹配情况相同
  • 当前字符 p[j-1]!='*' 时,当前字符 s[i-1] 和 p[j-1]必须匹配,同时之前的字符串 s[0,i-1)和p[0,j-1)必须匹配, s[0,i)和p[0,j)才能匹配
dp[i][j] = i > 0 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.') && dp[i - 1][j - 1]

整体代码如下:

public class Solution {
public boolean isMatch(String s, String p) {
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
dp[0][0] = true; for (int i = 0; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) { // j从1开始,因为i>0,j=0的情况肯定不匹配
if (j > 1 && p.charAt(j - 1) == '*') {
dp[i][j] = dp[i][j - 2] || (i > 0 && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.') && dp[i - 1][j]); // dp[i][j-2]表示*前的字符匹配0次,后面的表示匹配1次以上
} else {
// 不为*的时候,需要当前两个字符匹配,同时dp[i-1][j-1]
dp[i][j] = i > 0 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.') && dp[i - 1][j - 1];
}
}
}
return dp[s.length()][p.length()];
}
}

[LeetCode] 10. Regular Expression Matching ☆☆☆☆☆的更多相关文章

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

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

  2. Leetcode 10. Regular Expression Matching(递归,dp)

    10. Regular Expression Matching Hard Given an input string (s) and a pattern (p), implement regular ...

  3. leetcode 10. Regular Expression Matching 、44. Wildcard Matching

    10. Regular Expression Matching https://www.cnblogs.com/grandyang/p/4461713.html class Solution { pu ...

  4. [LeetCode] 10. Regular Expression Matching 正则表达式匹配

    Given an input string (s) and a pattern (p), implement regular expression matching with support for  ...

  5. LeetCode (10): Regular Expression Matching [HARD]

    https://leetcode.com/problems/regular-expression-matching/ [描述] Implement regular expression matchin ...

  6. [LeetCode] 10. Regular Expression Matching

    Implement regular expression matching with support for '.' and '*'. DP: public class Solution { publ ...

  7. Java [leetcode 10] Regular Expression Matching

    问题描述: Implement regular expression matching with support for '.' and '*'. '.' Matches any single cha ...

  8. [leetcode]10. Regular Expression Matching正则表达式的匹配

    Given an input string (s) and a pattern (p), implement regular expression matching with support for  ...

  9. 蜗牛慢慢爬 LeetCode 10. Regular Expression Matching [Difficulty: Hard]

    题目 Implement regular expression matching with support for '.' and '*'. '.' Matches any single charac ...

随机推荐

  1. windows10下git一些问题

    windows10下安装git 找不到ssh解决办法 解决办法是: 输入下列命令,一路回车 $ ssh-keygen -t rsa -C “邮箱地址” 若执行ssh-add /path/to/xxx. ...

  2. 基于Kubernetes(k8s)的RabbitMQ 集群

    目前,有很多种基于Kubernetes搭建RabbitMQ集群的解决方案.今天笔者今天将要讨论我们在Fuel CCP项目当中所采用的方式.这种方式加以转变也适用于搭建RabbitMQ集群的一般方法.所 ...

  3. .Net并行编程 - Reactive Extensions(Rx)并发浅析

    关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...

  4. Python中的eval

    Python中的eval方法接受一个字符串参数,并且把字符串里面的内容当成Python代码来执行: eval的缺点是执行速度慢,并且会有安全风险

  5. python 项目配置虚拟环境

    # Windows 环境1, 安装 Visual C++ 2015 Build Tools, 依赖.Net Framework 4.6, 安装包位置 ./tools/windows/visualcpp ...

  6. LintCode-380.两个链表的交叉

    两个链表的交叉 请写一个程序,找到两个单链表最开始的交叉节点. 注意事项 如果两个链表没有交叉,返回null. 在返回结果后,两个链表仍须保持原有的结构. 可假定整个链表结构中没有循环. 样例 下列两 ...

  7. pycharm开启代码智能提示和报错提示

    天呐,经历了一大波周折,终于把提示给弄好了,加入没有提示的话,pycharm就是一个空格了,没有什么作用,对我来说,真的是很困难的事情,所以无论如何都要去把这个智能提示给搞好了. 先讲讲我的经历吧.我 ...

  8. 软工网络15团队作业4——Alpha阶段敏捷冲刺-4

    一.当天站立式会议照片: 二.项目进展 昨天已完成的工作: 完成程序副界面的设计与信息的输入统计 明天计划完成的工作: 日期等细致信息的处理 工作中遇到的困难: 对微信小程序开发的代码构成有了一些了解 ...

  9. HDU 2148 Score

    http://acm.hdu.edu.cn/showproblem.php?pid=2148 Problem Description 转眼又到了一年的年末,Lele又一次迎来了期末考试.虽然说每年都要 ...

  10. PHP给图片添加图片水印

    涉及到的函数: 1.file_get_contents():用于将文件的内容读入到一个字符串中的首选方法.如果操作系统支持,还会使用内存映射技术来增强性能. 2.list():list() 函数用于在 ...