【Algorithms 4】算法(第4版)学习笔记 23 - 5.4 正则表达式

news2024/11/26 0:31:14

文章目录

    • 前言
    • 参考目录
    • 学习笔记
      • 1:正则表达式
      • 1.1:表示
      • 1.2:快捷表示
      • 2:正则表达式与非确定有限状态自动机 REs and NFAs
      • 2.1:二元性
      • 2.2:模式匹配实现
      • 2.3:非确定有限状态自动机 Nondeterministic finite-state automata
      • 2.4:非确定性
      • 3:NFA 模拟
      • 3.1:demo 演示
      • 3.2:Java 实现
      • 3.3:分析
      • 4:NFA 构造
      • 4.1:构造与正则表达式对应的 NFA
      • 4.2:实现
      • 4.3:demo 演示
      • 4.4:Java 实现
      • 4.5:分析
      • 5:非正则表达式
      • 6:背景
      • 7:小结

前言

本篇主要内容包括:正则表达式非确定有限状态自动机 NFA

建议在学习本篇之前先行学习或回顾上一篇子字符串查找的内容。

参考目录

  • B站 普林斯顿大学《Algorithms》视频课
    (请自行搜索。主要以该视频课顺序来进行笔记整理,课程讲述的教授本人是该书原版作者之一 Robert Sedgewick。)
  • 微信读书《算法(第4版)》
    (本文主要内容来自《5.4 正则表达式》)
  • 官方网站
    (有书本配套的内容以及代码)

学习笔记

注1:下面引用内容如无注明出处,均是书中摘录。
注2:所有 demo 演示均为视频 PPT demo 截图。
注3:如果 PPT 截图中没有翻译,会在下面进行汉化翻译,因为内容比较多,本文不再一一说明。

1:正则表达式

1.1:表示

![L20-54RegularExpressions_06]

对应书本章节:《5.4.1 使用正则表达式描述模式》

  • 5.4.1.1 连接操作
  • 5.4.1.2 或操作
  • 5.4.1.3 闭包操作
  • 5.4.1.4 括号

1.2:快捷表示

![L20-54RegularExpressions_07]

对应书本章节:《5.4.2 缩略写法》

  • 5.4.2.1 字符集描述符
  • 5.4.2.2 闭包的简写
  • 5.4.2.3 转义序列

2:正则表达式与非确定有限状态自动机 REs and NFAs

2.1:二元性

![L20-54RegularExpressions_16]

RE(正则表达式): 简洁描述一组字符串的方法。
DFA(确定有限状态自动机): 一种机器,用于判断给定的字符串是否属于预定义的字符串集合。

克林宁定理(Kleene’s theorem):

  • 对于任何确定有限状态自动机(DFA),都存在一个能够描述相同字符串集合的正则表达式(RE)。
  • 对于任何正则表达式(RE),都存在一个能够识别相同字符串集合的确定有限状态自动机(DFA)。

2.2:模式匹配实现

![L20-54RegularExpressions_18]

类似于 KMP 算法:

  • 不需要文本输入流回溯。
  • 确保二次时间复杂度(通常为线性时间)。

基础抽象概念: 非确定有限状态自动机(NFA)。

基本策略:[应用克林宁定理]

  • 从正则表达式构建 NFA。
  • 使用文本作为输入模拟 NFA。

2.3:非确定有限状态自动机 Nondeterministic finite-state automata

![image-20240402093803403]

对应书本章节:《5.4.4 非确定有限状态自动机》。

![image-20240402094701193]

也有可能进入错误状态并停滞:

![image-20240402095141143]

![image-20240402095201507]

2.4:非确定性

![L20-54RegularExpressions_23]

Q. 如何确定一个字符串是否被自动机所匹配?
DFA(确定有限状态自动机): 判定较为简单,因为对于每个状态和输入字符,恰好有一个适用的转换。
NFA(非确定有限状态自动机): 可能存在多个适用的转换;需要正确选择其中一个!

Q. 如何模拟 NFA?
A. 系统地考虑所有可能的转换序列来进行模拟。

3:NFA 模拟

3.1:demo 演示

![image-20240402163328370]

![image-20240402163446270]

该 demo 建议多观看几遍视频理解操作步骤。

3.2:Java 实现

edu.princeton.cs.algs4.NFA

![image-20240402164427969]
edu.princeton.cs.algs4.NFA#NFA

/**
     * Initializes the NFA from the specified regular expression.
     *
     * @param  regexp the regular expression
     */
    public NFA(String regexp) {
        this.regexp = regexp;
        m = regexp.length();
        Stack<Integer> ops = new Stack<Integer>();
        graph = new Digraph(m+1);
        for (int i = 0; i < m; i++) {
            int lp = i;
            if (regexp.charAt(i) == '(' || regexp.charAt(i) == '|')
                ops.push(i);
            else if (regexp.charAt(i) == ')') {
                int or = ops.pop();

                // 2-way or operator
                if (regexp.charAt(or) == '|') {
                    lp = ops.pop();
                    graph.addEdge(lp, or+1);
                    graph.addEdge(or, i);
                }
                else if (regexp.charAt(or) == '(')
                    lp = or;
                else assert false;
            }

            // closure operator (uses 1-character lookahead)
            if (i < m-1 && regexp.charAt(i+1) == '*') {
                graph.addEdge(lp, i+1);
                graph.addEdge(i+1, lp);
            }
            if (regexp.charAt(i) == '(' || regexp.charAt(i) == '*' || regexp.charAt(i) == ')')
                graph.addEdge(i, i+1);
        }
        if (ops.size() != 0)
            throw new IllegalArgumentException("Invalid regular expression");
    }

edu.princeton.cs.algs4.NFA#recognizes

/**
     * Returns true if the text is matched by the regular expression.
     *
     * @param  txt the text
     * @return {@code true} if the text is matched by the regular expression,
     *         {@code false} otherwise
     */
    public boolean recognizes(String txt) {
        DirectedDFS dfs = new DirectedDFS(graph, 0);
        Bag<Integer> pc = new Bag<Integer>();
        for (int v = 0; v < graph.V(); v++)
            if (dfs.marked(v)) pc.add(v);

        // Compute possible NFA states for txt[i+1]
        for (int i = 0; i < txt.length(); i++) {
            if (txt.charAt(i) == '*' || txt.charAt(i) == '|' || txt.charAt(i) == '(' || txt.charAt(i) == ')')
                throw new IllegalArgumentException("text contains the metacharacter '" + txt.charAt(i) + "'");

            Bag<Integer> match = new Bag<Integer>();
            for (int v : pc) {
                if (v == m) continue;
                if ((regexp.charAt(v) == txt.charAt(i)) || regexp.charAt(v) == '.')
                    match.add(v+1);
            }
            if (match.isEmpty()) continue;

            dfs = new DirectedDFS(graph, match);
            pc = new Bag<Integer>();
            for (int v = 0; v < graph.V(); v++)
                if (dfs.marked(v)) pc.add(v);

            // optimization if no states reachable
            if (pc.size() == 0) return false;
        }

        // check for accept state
        for (int v : pc)
            if (v == m) return true;
        return false;
    }

3.3:分析

![L20-54RegularExpressions_32]

对应书本命题 Q:

![image-20240402164943402]

4:NFA 构造

4.1:构造与正则表达式对应的 NFA

![L20-54RegularExpressions_34]

状态: 为正规表达式(RE)中的每个符号创建一个状态,同时添加一个接受状态。

![L20-54RegularExpressions_35]

连接操作: 从字母表中字符对应的当前状态添加匹配转换边至下一个状态。

![L20-54RegularExpressions_36]

括号: 从括号所在的状态添加一条 ε - 转换边至下一个状态。

![L20-54RegularExpressions_37]

闭包操作: 对于每一个运算符,添加三条 ε - 转换边。

![L20-54RegularExpressions_38]

或表达式: 对于每一个 |(逻辑或)操作符,添加两条 ε - 转换边。

4.2:实现

![L20-54RegularExpressions_39]

目标: 编写一个程序来构建 ε - 转换有向图。

挑战: 记忆左括号以实现闭包和逻辑或;记忆逻辑或符号 | 以实现逻辑或操作。

解决方案: 维护一个栈结构。

  • 遇到 ( 符号时:将 ( 入栈。
  • 遇到 | 符号时:将 | 入栈。
  • 遇到 ) 符号时:弹出与之配对的 ( 及其间的所有 | 符号;然后根据闭包和逻辑或的规则,添加相应的 ε - 转换边。

4.3:demo 演示

![image-20240402173630494]

4.4:Java 实现

![L20-54RegularExpressions_42]

4.5:分析

![L20-54RegularExpressions_43]

对应书本命题 R:

![image-20240402174323446]

5:非正则表达式

![L20-54RegularExpressions_53]

反向引用:

  • \1 表示法用于匹配先前已匹配到的子表达式。
  • 这一特性在典型的正则表达式实现中得到支持。

某些非正则表达式的例子:

  • 形如 ww 的字符串,其中 w 是任意字符串,例如 beriberi
  • 包含复合数量 1 的单字符字符串,例如 111111
  • 含有相同数量 0 和 1 的二进制字符串,例如 01110100
  • Watson-Crick 互补的回文串,例如 atttcggaaat

注解: 使用反向引用进行模式匹配的问题属于难解问题(不可行或计算复杂度较高)。

6:背景

![L20-54RegularExpressions_54]

抽象机、语言及非确定性概念:

  • 是计算理论的基础。
  • 自20世纪30年代以来就被深入研究。
  • 是现代编程语言的基础。

编译器:

  • 编译器是一种程序,负责将源程序翻译成机器码。
  • KMP 算法处理的字符串模式可以转换为确定有限自动机(DFA)。
  • grep 工具使用的正则表达式可以转换为非确定有限自动机(NFA)。
  • javac 编译器将 Java 语言源代码编译为 Java 字节码。

7:小结

![L20-54RegularExpressions_55]

程序员:

  • 通过 DFA 模拟实现子串搜索功能。
  • 通过 NFA 模拟实现正则表达式模式匹配。

理论学者:

  • 正则表达式是描述一组字符串的紧凑表示方法。
  • NFA 是非确定性抽象机,其功能等价于正则表达式。
  • DFA、NFA 以及正则表达式都有其局限性。

你: 实际应用计算机科学的核心原理。

举例说明计算机科学中的关键范例:

  • 构建中间抽象层。
  • 挑选恰当的抽象模型!
  • 解决重要的实际问题。

(完)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql锁表问题

问题描述 偶尔应用日志会打印锁表超时回滚 org.springframework.dao.CannotAcquireLockException: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transactionmysql锁…

Python基础之pandas:文件读取与数据处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、文件读取1.以pd.read_csv()为例&#xff1a;2.数据查看 二、数据离散化、排序1.pd.cut()离散化&#xff0c;以按范围加标签为例2. pd.qcut()实现离散化3.排序4.…

原型链污染攻击也称JavaScript Prototype 污染攻击

JavaScript数据类型 let和var关键字的区别 使用var或let关键字可以定义变量 let和var的区别如下&#xff1a; var是全局作用域&#xff0c;let 只在当前代码块内有效 当在代码块外访问let声明的变量时会报错 var有变量提升&#xff0c;let没有变量提升 let必须先声明…

一文秒解四大经典限流算法

阅读前提&#xff1a;没有最好的算法&#xff0c;只有最适合的算法&#xff01; 限流算法&#xff1a; 固定窗口限流算法 滑动窗口限流算法 漏桶限流算法 令牌桶限流算法 固定窗口限流算法 介绍 固定窗口限流算法&#xff08;Fixed Window Rate Limiting Algorithm&#…

算法知识点汇总

知识点 1. 求二进制中1的个数 int get_count(int x)//返回x的二进制有多少个1 int get_count(int x) {int res 0;while (x){res ;x - x & -x;}return res; }2. 建树&#xff0c;和树的DFS 记得初始化头节点 const int N 1e5 10, M N * 2; int h[N], e[M], ne[M], id…

【OpenCV】 基础入门(一)初识 Mat 类 | 通过 Mat 类显示图像

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【OpenCV • c】计算机视觉&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff…

OR-352,兼容替代TLP187/TLP127/EL452等,达灵顿光耦

低输入正向电流 高电流传输比 DC和AC输入 电平转换 高输入输出隔离电压和高集电极发射极电压 特征 电流传输比&#xff08;IF 1mA&#xff0c;VCE 2V时&#xff0c;CTR &#xff1a; 最小1000%&#xff09; 高集电极-发射极电压 &#xff08;VCEO 300V&#xff09; …

mongodb的简单操作

文章目录 前言数据库的创建和删除集合的创建和删除文档的插入和查询异常处理更新数据局部修改符合条件的批量更新加操作 删除文档删除全部数据删除符合条件的数据 统计count统计有多少条数据统计特定条件有多少条数据 分页查询排序查询正则查询比较查询包含查询条件连接查询索引…

Python疑难杂症(16)---Numpy知识集合(四)列出Numpy模块的常用函数,供查询参考。

列出Numpy模块的常用函数&#xff0c;供查询参考。 numpy.array:创建新的NumPy数组 numpy.zeros:创建一个以零填充的数组。 numpy.random:生成随机数组的函数。 numpy.linspace:在指定范围内生成均匀间隔的数字。 numpy.range:用间隔的值创建数组。 numpy.shape:返回一个…

AWS-EKS 给其他IAM赋予集群管理权限

AWS EKS 设计了权限管理系统&#xff0c;A用户创建的集群 B用户是看不到并且不能管理和使用kubectl的&#xff0c;所以我们需要共同管理集群时就需要操场共享集群访问给其他IAM用户。 两种方式添加集群控制权限&#xff08;前提&#xff1a;使用有管理权限的用户操作&#xff…

睡岗检测识别系统

智驱力睡岗检测识别系统是一种基于人工智能技术的监控系统&#xff0c;旨在通过视频分析来识别和报警那些在工作岗位上出现睡觉行为的人员。这种系统通常应用于需要24小时监控的关键岗位&#xff0c;如银行、营业厅、监控中心等场所。系统能够自动分析监控画面&#xff0c;当检…

如何在比特币上验证ZK Proofs

1. 引言 前序博客有&#xff1a; 基于BitVM的乐观 BTC bridgeBitVM&#xff1a;Bitcoin的链下合约Bitcoin Bridge&#xff1a;治愈还是诅咒&#xff1f;BitVM2&#xff1a;比特币上的无需许可验证以比特币脚本来实现SNARK VerifierClementine&#xff1a;Citrea的基于BitVM的…

鸿蒙HarmonyOS应用开发之NativeBundle开发指导

场景介绍 开发者可以通过本指导了解在OpenHarmony应用中&#xff0c;如何使用Native Bundle接口获取应用自身相关信息。 接口说明 开发步骤 1. 创建工程 2. 添加依赖 创建完成后&#xff0c;IDE会在工程生成cpp目录&#xff0c;目录有libentry/index.d.ts、hello.cpp、CMak…

XenCenter 2024 导入虚拟机

导入虚拟机 虚拟机位置 导入到那一个服务器 导入虚拟机存放存储位置 虚拟机网卡配置 SR修复功能&#xff0c;看自己需求 虚拟机恢复确认最终配置 恢复好的虚拟机 虚拟机模板转换

上位机图像处理和嵌入式模块部署(qmacvisual图像清晰度)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 做过isp的同学都知道&#xff0c;图像处理里面有一个3A&#xff0c;即自动曝光、自动白平衡和自动对焦。其中自动对焦这个&#xff0c;就需要用输入…

HbnnMall电子商城系统介绍(功能与技术栈)

今天在看自己网站上的文章时&#xff0c;看到了曾经开发的电商系统。那是在2020年&#xff0c;来到小米两年后&#xff0c;我已经对各个业务线&#xff0c;各种专业知识有了系统性的了解和学习&#xff0c;所以想自己动手写一个电商系统&#xff0c;以便进一步提高自己的技术。…

【数论】莫比乌斯反演(欧拉反演)进阶-杜教筛

文章目录 前言 回忆 题集12 杜教筛例题 前言 这里需要对莫反有一些基础。 不会的可以点这里 回忆 f ( n ) ∑ d ∣ n g ( d ) → g ( n ) ∑ d ∣ n f ( d ) μ ( n d ) f(n)\sum_{d|n}g(d)\rightarrow g(n)\sum_{d|n}f(d)\mu(\frac{n}{d}) f(n)∑d∣n​g(d)→g(n)∑d∣n​…

vue3+eachrts饼图轮流切换显示高亮数据

<template><div class"charts-box"><div class"charts-instance" ref"chartRef"></div>// 自定义legend 样式<div class"charts-note"><span v-for"(items, index) in data.dataList" cla…

unity之 “Allow ‘unsafe‘ code“ 在哪里。

导入unity中的代码&#xff0c;出现如下错误&#xff0c;该如何解决&#xff1f; Unsafe code may only appear if compiling with /unsafe. Enable "Allow unsafe code" in Player Settings to fix this error 解决这个问题&#xff0c;只需要设置就可以。 设置的地…

【苍穹外卖】log爆红

使用了Slf4j注解&#xff0c;用于自动生成一个log对象&#xff0c;相当于private final Logger log LoggerFactory.getLogger(当前类名.class); 这个注解需要安装Lombok插件才能使用。 IDEA file—settings–plugins&#xff0c;搜索lombok–install。安装完后自动重启IDEA后…