LeetCode #10

本贴最后更新于 2299 天前,其中的信息可能已经东海扬尘

问题:模拟正则表达式中的.和 *

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

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

说明:

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

解答:
这是比较困难的一道题。官方中文站的通过率只有不到 1/4。其实想清楚正则的匹配过程也不难。主要有以下几点:
0. 正则匹配以正则单元为单位,普通字符也算正则单元,特殊的,如果有*,则其与前一个字符结合为一个正则单元。

  1. java 的正则表达式是 NFA,默认是贪婪匹配,也就是说每个正则单元(记为 pi)会尽可能多的匹配目标字符串(s)。
  2. 当前正则单元存在*时,既可尝试匹配当前目标字符也可跳到下一个单元,默认是尝试匹配。
  3. 如若当前单元不匹配,则回退到上一次存在匹配分岔的位置(状态)去尝试。
  4. 如若模式和字符串都匹配完了,则匹配成功。
  5. 如若字符串匹配完了,正则式无法匹配完则失败,反之亦然。
  6. 如没有可退回的位置,则匹配失败。
  7. 注意边界情况。

如果想系统学习正则表达式可找《精通正则表达式》这本书来看看,力荐。

这里用一个链表模拟栈,记录每次分岔的状态(下次可尝试匹配的状态)

package xyz.quxiao.play.lab.leetcode;

import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;

/**
 * @author 作者 :quxiao 创建时间:2018/9/3 22:39
 */public class Problem10 {

  public static void main(String[] args) {
    Problem10 problem10 = new Problem10();
//    System.out.println(problem10.isMatch("abcda", ".*a.*c*da"));
//    System.out.println(problem10.isMatch("aa", "a*"));
//    System.out.println(problem10.isMatch("aab", "c*a*b"));
//    System.out.println(problem10.isMatch("aab", ".*"));
//    System.out.println(problem10.isMatch("mississippi", "mis*is*p*."));
//    System.out.println(problem10.isMatch("abc", "abcc"));
//    System.out.println(problem10.isMatch("", "a*c*"));
//    System.out.println(problem10.isMatch("aac", ".*.*a*c"));
  System.out.println(problem10.isMatch("aacd", ".*.*a*c"));
    System.out.println(problem10.isMatch("", ""));
  }

  public boolean isMatch(String s, String p) {
    if (s == null) {
      s = "";
    }
    if (p == null) {
      p = "";
    }
    int star = "*".charAt(0);
    // 提取匹配单元
  List patternUnit = new ArrayList<>();
    for (int i = 0; i < p.length(); i++) {
      int j = i + 1;
      if (j < p.length() && p.charAt(j) == star) {
        patternUnit.add(p.substring(i, i + 2));
        i++;
      } else {
        patternUnit.add(p.substring(i, i + 1));
      }
    }
    // 
  LinkedList> matchQueue = new LinkedList<>();
    int i = 0;
    int j = 0;
    // 当还没匹配完时
  while (true) {
      if (i == s.length() && j == patternUnit.size()) {
        return true;
      }

      if (j == patternUnit.size()) {
        if (matchQueue.isEmpty()) {
          return false;
        } else {
          Entry pop = matchQueue.pop();
          i = pop.getKey();
          j = pop.getValue();
          continue;
        }
      }

      String pattern = patternUnit.get(j);
      String str = getChar(s, i);
      if (pattern.contains("*")) {
        matchQueue.add(0, new SimpleEntry<>(i, j + 1));
        if (unitMatch(str, pattern)) {
          // 推进
  i++;
          // 注意i可能因为向前推进导致超过边界,这里不分辨是否在边界上,超出时依然让j向前推进
  if (i >= s.length()) {
            j++;
          }
          continue;
        } else {
          if (matchQueue.isEmpty()) {
            return false;
          } else {
            Entry pop = matchQueue.pop();
            i = pop.getKey();
            j = pop.getValue();
            continue;
          }
        }
      } else {
        if (unitMatch(str, pattern)) {
          // 推进
  i++;
          j++;
          continue;
        } else {
          if (matchQueue.isEmpty()) {
            return false;
          } else {
            Entry pop = matchQueue.pop();
            i = pop.getKey();
            j = pop.getValue();
            continue;
          }
        }
      }
    }
  }

  private boolean unitMatch(String character, String unit) {
    if (unit.startsWith(".")) {
      return true;
    } else if (character == null && unit.contains("*")) {
      return true;
    } else if (character == null){
      return false;
    } else {
      return unit.startsWith(character);
    }
  }

  private String getChar(String s, int pos) {
    if (pos >= s.length()) {
      return null;
    }
    return s.substring(pos, pos + 1);
  }
}
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • 算法
    428 引用 • 254 回帖 • 24 关注
  • 链表
    12 引用 • 6 回帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 651 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 24 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 639 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 700 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    223 引用 • 474 回帖
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • 招聘

    哪里都缺人,哪里都不缺人。

    190 引用 • 1057 回帖
  • danl
    147 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • V2Ray
    1 引用 • 15 回帖 • 1 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 627 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 102 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 370 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 604 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 439 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖 • 1 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 372 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖 • 1 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    88 引用 • 1235 回帖 • 408 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 670 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1706 回帖
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    167 引用 • 1520 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖 • 1 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖 • 1 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 1 关注