【每日一题】Leetcode - 10. 正则表达式匹配

题目

Leetcode - 10. 正则表达式匹配

解题思路

  • 预处理正则表达式,合并同项,比如: "a * b * c * . * " -> " . * "
  • 更加预处理后的正则表达式,构建NFA
  • 通过NFA状态转移条件一个一个匹配字符串字符
  • 不匹配的状态要回退
  • 匹配完字符串了,且该状态是可结束的,就true,否则false

c * b * a * 这种正则,构造NFA时,标记a是可结束,但是其实c, b也可结束
a * b * c 这种正则,构造NFA时,a和b都可以是c的父节点

class Solution {public boolean isMatch(String s, String p) {if (p.equals(".*")) {return true;}//  pretreatment patternp = pretreatment(p);if (p.equals(".*")) {return true;}//  constructNFAState root = constructNFA(p);//  match sSet<State> states = matchStates(root, s.charAt(0));for (State state : states) {boolean flag = doMatch(s, 0, state);if (flag) {return true; // it has any one matched}}return false;}private static class State {//  this state's parentsSet<State> parents = new HashSet<>();//  <condition, states> : the table denotes map to next state by conditionMap<Character, Set<State>> nextStates = new HashMap<>();//  this state is last stateboolean isEnd = false;}private String pretreatment(String p) {//  pretreatment pattern//  merge follow pattern//      a* b* ... c*.* -> .*//      a* a* ... a*a* -> a*//      .* a* ... .*b* -> .*char[] preP = new char[p.length()];int prePIndex = -1;for (int i = 0; i < p.length(); i++) {char ch = p.charAt(i);preP[++prePIndex] = ch;if (ch != '*') {continue;}// .*if (p.charAt(i - 1) == '.') { // .* a* ... .*b* -> .*while (i + 2 < p.length() && p.charAt(i + 2) == '*') {i += 2;}continue;}//  a*int j = i;boolean flag = false;while (j + 2 < p.length() && p.charAt(j + 2) == '*') {if (p.charAt(j + 1) == '.') {flag = true;break;}j += 2;}if (flag) { //  a* b* ... c*.* -> .*preP[prePIndex - 1] = '.';i = j + 2;while (i + 2 < p.length() && p.charAt(i + 2) == '*') {i += 2;}continue;}//  a* a* ... a*a* -> a*while (i + 2 < p.length() && p.charAt(i + 2) == '*') {if (p.charAt(i + 1) != preP[prePIndex - 1]) {break;}i += 2;}}p = new String(preP, 0, prePIndex + 1);return p;}private State constructNFA(String p) {State newState = new State();State root = newState;for (int i = 0; i < p.length(); i++) {char ch = p.charAt(i);Set<State> states;if (ch != '*') {states = root.nextStates.computeIfAbsent(ch, k -> new HashSet<>());State state = new State();states.add(state);if (i >= 1 && p.charAt(i - 1) == '*') {repeatedParentAddState(root, ch, state);}state.parents.add(root);root = state;if (i == p.length() - 1) {root.isEnd = true;}continue;}//  x* -> get xch = p.charAt(i - 1);states = root.nextStates.computeIfAbsent(ch, k -> new HashSet<>());states.add(root); // x+ : contain one and more oneroot.parents.add(root); // x{0} : no contain//  before two steps achieve x*if (i == p.length() - 1) {root.isEnd = true;repeatedParentMarkEnd(root);}}return newState;}public boolean doMatch(String s, int cur, State state) {if (cur + 1 == s.length()) {return state.isEnd;}Set<State> states = matchStates(state, s.charAt(cur + 1));for (State state1 : states) {boolean flag = doMatch(s, cur + 1, state1);if (flag) {return true;}}return false;}public Set<State> matchStates(State root, char ch) {//  get states by conditionSet<State> states = root.nextStates.get(ch);if (states == null) {states = new HashSet<>();}//  get states by especial condition of '.', because it can match any charSet<State> states1 = root.nextStates.get('.');if (states1 != null) {states.addAll(states1);}return states;}private void repeatedParentMarkEnd(State root) {if (!root.parents.contains(root)) {return;}for (State parent : root.parents) {if (parent == root) {continue;}parent.isEnd = true;repeatedParentMarkEnd(parent);}}private void repeatedParentAddState(State root, char ch, State state) {if (!root.parents.contains(root)) {return;}for (State rootParent : root.parents) {Set<State> states = rootParent.nextStates.get(ch);if (states != null) {if (states.contains(state)) {continue;}states.add(state);}else {states = new HashSet<>();states.add(state);rootParent.nextStates.put(ch, states);}repeatedParentAddState(rootParent, ch, state);}}}

在这里插入图片描述

优化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/5985.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

13年12月CCF计算机软件能力认证(csp认证) 内有c++和Python代码

第一题&#xff1a;出现次数最多的数 给定 n 个正整数&#xff0c;找出它们中出现次数最多的数。 如果这样的数有多个&#xff0c;请输出其中最小的一个。 输入格式 输入的第一行只有一个正整数 n&#xff0c;表示数字的个数。 输入的第二行有 n 个整数 s1,s2,…,sn。 相邻的数…

3.FreeRTOS系统源码移植

目录 一、获取FreeRTOS源代码 二、FreeRTOS系统源码内容 三、FreeRTOS系统源码移植 一、获取FreeRTOS源代码 来FreeRTOS官方网站:https://www.freertos.org/ 我这里主要提供的是例程为FreeRTOS的V10.4.6版本 1、进入官网&#xff0c;点击Download FreeRTOS 2、点击Downl…

浅析厂房仓库电气火灾的成因及对策

贾丽丽 安科瑞电气股份有限公司 上海嘉定201801 摘 要: 文章分析了厂房仓库电气火灾的成因及火灾特点 ,并有针对性地提出了预防火灾的对策。 关键词: 厂房仓库&#xff1b;电气火灾&#xff1b;成因&#xff1b;预防对策 0 前 言 随着国际经济的全球化,国内经济建设迅猛发…

时间序列分解 | Matlab改进的自适应噪声完备集合经验模态分解ICEEMDAN

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列分解 | Matlab改进的自适应噪声完备集合经验模态分解ICEEMDAN 部分源码 %--------------------

Hadoop 集群如何升级?

前言 本文隶属于专栏《大数据技术体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见大数据技术体系 正文 升级 Hadoop 集群需要细致的规划&#xff0c;特…

手把手教你搭建SpringCloudAlibaba之Sentinel规则持久化

SpringCloud Alibaba全集文章目录&#xff1a; 零、手把手教你搭建SpringCloudAlibaba项目 一、手把手教你搭建SpringCloud Alibaba之生产者与消费者 二、手把手教你搭建SpringCloudAlibaba之Nacos服务注册中心 三、手把手教你搭建SpringCloudAlibaba之Nacos服务配置中心 …

IIC(I2C)协议

I2C&#xff08;Inter-Integrated Circuit&#xff09;:是一种串行通信协议&#xff0c;用于在集成电路之间进行数据传输。它由飞利浦公司开发&#xff0c;并广泛应用在各种电子设备和传感器之间进行通信。 I2C通信协议由两根线组成&#xff1a; 一个是用于数据传输的串行数据线…

MySQL 主从复制与读写分离

概念 主从复制与读写分离的意义 企业中的业务通常数据量都比较大&#xff0c;而单台数据库在数据存储、安全性和高并发方面都无法满足实际的需求&#xff0c;所以需要配置多台主从数据服务器&#xff0c;以实现主从复制&#xff0c;增加数据可靠性&#xff0c;读写分离&#x…

HTTP模式下STM32程序远程升级设计

针对嵌入式终端设备架设分散、数量庞大以及应用程序更新迭代速度快带来的程序升级困难局面&#xff0c;运用STM32微控制器的在应用中编程&#xff08;IAP&#xff09;原理&#xff0c;设计了通过以太网远程升级程序的方案。 HTTP协议和LwIP协议的使用&#xff0c;不仅让整个方…

0基础学习VR全景平台篇,第51篇:高级功能-自定义菜单

大家好&#xff0c;欢迎观看蛙色VR官方系列——后台使用课程&#xff01; 本期为大家带来蛙色VR平台&#xff0c;高级功能-自定义菜单&#xff01; 功能位置示意 一、本功能将用在哪里&#xff1f; 自定义菜单&#xff0c;是显示在VR漫游作品底部和顶部各种可点击的图标按钮。…

Nginx(7)Nginx实现服务器端集群搭建

Nginx集群搭建 Nginx与Tomcat部署Nginx实现动静分离Nginx实现Tomcat集群搭建 Nginx高可用解决方案KeepalivedKeepalived配置文件keepalived之vrrp_script Nginx制作下载站点Nginx的用户认证模块 Nginx与Tomcat部署 前面课程已经将Nginx的大部分内容进行了讲解&#xff0c;我们…

如何通过用户场景分析挖掘需求痛点?4大角度

在我们日常需求分析过程中&#xff0c;往往忽视对用户场景的深入分析和挖掘&#xff0c;造成伪需求和需求缺失等问题。 而真正的用户需求&#xff0c;只有在对应的应用场景下才会真正呈现出来。因此我们需要重视对用户场景分析&#xff0c;深入挖掘用户需求痛点。而在对用户场景…