LeetCode #10

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

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

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

匹配应该覆盖整个字符串 (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 回帖
  • 算法
    437 引用 • 254 回帖 • 24 关注
  • 链表
    12 引用 • 6 回帖

相关帖子

回帖

欢迎来到这里!

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

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

推荐标签 标签

  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 17 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 701 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    246 引用 • 1338 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 5 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 499 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 183 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖 • 5 关注
  • Markdown

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

    170 引用 • 1529 回帖
  • Follow
    4 引用 • 12 回帖 • 11 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2040 回帖
  • RemNote
    2 引用 • 16 回帖 • 14 关注
  • Anytype
    3 引用 • 31 回帖 • 16 关注
  • 倾城之链
    23 引用 • 66 回帖 • 168 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    174 引用 • 3853 回帖
  • 阿里巴巴

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

    43 引用 • 221 回帖 • 60 关注
  • 996
    13 引用 • 200 回帖 • 8 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 13 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 2 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 177 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    91 引用 • 59 回帖 • 3 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 629 关注
  • 微软

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

    8 引用 • 44 回帖
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    91 引用 • 384 回帖