自己实现一个 DFA 串模式识别器

前言

这是我编译原理课程的实验。希望读完这篇文章的人即便不知道 NFA,DFA 和正规表达式是什么,也能够对它们有一个简单的理解,并能自己去实现一个能够识别特定模式的串模式识别器。它可能会像是这样:

  1. 输入一个正规表达式:(s.f.l*.e)|(a*.b*)

  2. 输入:“sfe”

    输出:matched!

    输入:“sflea”

    输出:failed!

注:'.' (点字符)表示连接运算

​ 文章分为两部分,理论背景:介绍相关概念和原理;程序实现:使用 C++ 实现一个 DFA 串模式识别器。

理论背景

引入

​ 我比较喜欢将任何理论和技术从自己能应用和理解的最低点开始阐述,因为这样往往可以将新的知识与过往的知识体系相联结。同时在一定的场景下思考它如何被应用,以切实的实现将所学流畅的抵达所用。这篇文章亦是如此。

​ 首先我们要处理一个简单的问题,给出如下串:

​ 例一:

ab,abab,ababab,abababab,...

a,aa,aaa,aaaa,...

aab,aabaab,aabaabaab,...

​ 对于第一行给出的这些字符串,请问你是否能够编写简单程序,识别出给定的一个字符串 S 是否属于第一行中的某一个字符串?如 ab 属于第一行,abab 属于第一行,但 aab 不属于。我相信有过一定编程经验的人都可以通过简单的分支-循环逻辑,或者是一些字符串算法来写出一个判别程序。对于第二、三行也是如此。因为我们发现它们都具有一定的规律性,或者也可以称为遵循一定的模式。当情况很简单时我们并不用思考太多,只是不断的复杂化、堆叠我们的逻辑代码,希望代码逻辑能够捕获特定模式下所有的串。不过有时情况会很复杂,以至于我们非常困难去设计一个逻辑来实现判别(捕获模式)。比如下面这个串:

​ 例二:

abb,aabb,babb,ababb,aaaaaaabb,bbbbbbbbabb,aababbababbbabbabb,

ababababaaaaaaabbbbbbbaaaaaaabbbbbaababbbabababbabbbbaabb,...

​ 你可能会觉得这些串完全没有任何逻辑和规律可言嘛!没错,单凭对已给出的这些串很难发现规律。但是它确实有自己的模式,而且我可以提前告诉你,它们是由我根据正则(规)表达式:(a|b)*abb 产生的。如果你没有了解过正则(规)表达式也不必担心,先跳过它。

注:在某些不严格情况下,不区分正规表达式正则表达式

模式串和正规表达式

​ 在前文中,我重复了很多次模式这个词。其实我们之前看到的每一组串都是遵循特定的模式。非正式的,我们可以说 一组字符串构成的集合由一个与该组相关的称为模式的规则来描述。并且这个模式被说成匹配该集合中的每个字符串。

注:这里的模式特指 串的模式

​ 可以 以例一为例介绍模式。非正式的表示:

例一的第一行的模式为:由 a、b 交替出现组成的串

第二行模式为:由若干个 a 组成的串

第三行模式为:由若干个 abb 组成的串

​ 我们可以用自然语言描述简单的模式,但是无法去描述复杂的模式。所以就需要一种形式化的表示方法,来帮助我们表达。这就是正规表达式。正规表达式是表示模式的一种重要方法。每个模式匹配一个字符串集。简单来说,正规表达式需要一个字母表,其中字母表上的字符串是该字母表中符号的有穷序列。和定义在其上的一些运算。通过归纳已有的模式串,我们可以提出以下几种运算:

连接运算:以英文 '.' 表示。如:a.b 表示 串 ab

或运算:以英文 '|' 表示。如:a|b 表示串 a 或串 b

克林闭包运算:以英文 '*' 表示。如:a* 表示串:\(\epsilon\) ,a,aa,aaa,...

注:1. \(\epsilon\) 表示空串 2. 为了我的程序方便处理,我将连接运算设置成了 英文的点。

​ 需要注意的是,运算并不止上述三种,但是我们主要讨论他们,并且很多运算可以通过它们复合得到。如:

正闭包:以英文:'+' 表示,当字母表只有 a 时 a+ 等价于 a.a*

? 运算:以英文:'?' 表示,当字母表只有 a 时 a? 等价于 (a|\(\epsilon\))

指数运算等

​ 现在我们将例二中的正规表达式重新书写为:(a|b)*a.b.b 。参照上述运算的含义,我想你应该可以理解这个模式所代表的串的集合会是什么样的。

​ 注意,正规表达式所能描述的模式是有限的。它只能表示固定次数的重复或给定结构没有指定次数的重复。它不能用于描述均衡或者嵌套结构。如具有括号配对的符号串集合正规文法无法描述,但是可以通过更复杂的上下文无关文法来描述。关于文法不作多描述。

出于篇幅考虑和更好的阅读体验,本文将分成三个部分,欢迎继续阅读余下篇章。下一篇内容是正规表达式的实现原理,涉及 NFA、DFA 的概念和相关算法。

作者:Skipper

出处:https://www.cnblogs.com/backwords/p/12726258.html

本博客中未标明转载的文章归作者 Skipper 和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

自己实现一个 DFA 串模式识别器的更多相关文章

  1. 自己实现一个 DFA 串模式识别器(二)

    正规表达式的实现原理 ​ 上文讨论了串的模式的表达,即正规表达式.那么这一小节将讨论我们实现一个正规表达式的方法和原理.因为我们知道,一个正规表达式对应着一个串模式,而一个串模式又对应着一些列符合该模 ...

  2. MFC如何生成一个可串行化的类

    一.MFC允许对象在程序运行的整个过程中持久化的串行化机制 (1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程. (2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构 ...

  3. 公布一个基于 Reactor 模式的 C++ 网络库

    公布一个基于 Reactor 模式的 C++ 网络库 陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice 2010 Aug 30 本文主要介绍 muduo 网 ...

  4. VC++ MFC如何生成一个可串行化的类

    一.MFC允许对象在程序运行的整个过程中持久化的串行化机制(1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程.(2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构)的 ...

  5. python3 - 商品管理的程序,商品信息都存在一个json串里面

    商品管理的程序,商品信息都存在一个json串里面 1.查询商品信息 #校验商品是否存在 2.新增商品 # #校验商品是否存在 #校验价格是否合法 3.修改商品信息 ##校验商品是否存在 if chic ...

  6. CREATE SCHEMA - 定义一个新的模式

    SYNOPSIS CREATE SCHEMA schemaname [ AUTHORIZATION username ] [ schema_element [ ... ] ] CREATE SCHEM ...

  7. ZZNU-oj-2141:2333--【O(N)求一个数字串能整除3的连续子串的个数,前缀和数组+对3取余组合数找规律】

    2141: 2333 题目描述 “别人总说我瓜,其实我一点也不瓜,大多数时候我都机智的一批“ 宝儿姐考察你一道很简单的题目.给你一个数字串,你能判断有多少个连续子串能整除3吗? 输入 多实例输入,以E ...

  8. 【基本算法】 KMP文本串模式串的字符串匹配算法

    看了两个晚上的KMP,加上基本的“暴力匹配” 今晚看懂next[j]递归求解时,突然觉得算法真的好美妙,虽然觉悟的晚但晚胜过没有是吧! 我的博客都是应试性的学习笔记,不具备指导性,还是大神们写的好,例 ...

  9. BF算法(串模式匹配算法)

    主串和子串 主串与子串:如果串 A(如 "shujujiegou")中包含有串 B(如 "ju"),则称串 A 为主串,串 B 为子串.主串与子串之间的关系可简 ...

随机推荐

  1. Python - 面向对象(二)类方法、静态方法

    面向对象的各种方法 静态方法 - @staticmethod class Person(): name = "cool guy" @staticmethod def static( ...

  2. vscode如何配置debug,python正则表达式如何匹配括号,关于python如何导入自定义模块

    关于vscode如何配置debug的问题: 1.下载安装好python,并且配置好 环境变量 2.https://www.cnblogs.com/asce/p/11600904.html 3.严格按照 ...

  3. Contest 141

    2019-06-16 14:35:52 1089. Duplicate Zeros - Easy 问题描述: 问题求解: 很显然的可以使用O(n), O(n)的解法.主要问题在于如何在O(1)空间复杂 ...

  4. 微服务实战——高可用的SpringCloudConfig

    管理微服务配置 对于单体应用架构来说,会使用配置文件管理我们的配置,这就是之前项目中的application.properties或application.yml.如果需要在多环境下使用,传统的做法是 ...

  5. postgre安装和使用(R&Python)

    安装postgre http://helianthus-code.lofter.com/post/1dfe03e0_1c68233aa 这里选C更好 这里口令密码输入就是黑的 我装的时候反复报错,查了 ...

  6. OpenCV-Python 使用OCR手写数据集运行KNN | 五十四

    目标 在本章中 我们将使用我们在kNN上的知识来构建基本的OCR应用程序. 我们将尝试使用OpenCV自带的数字和字母数据集. 手写数字的OCR 我们的目标是构建一个可以读取手写数字的应用程序.为此, ...

  7. 使用 NLTK 对文本进行清洗,索引工具

    使用 NLTK 对文本进行清洗,索引工具 EN_WHITELIST = '0123456789abcdefghijklmnopqrstuvwxyz ' # space is included in w ...

  8. coding++:JS数组去重的几种常见方法

    一.简单的去重方法 // 最简单数组去重法 /* * 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中 * IE8以下不支持数组的indexOf方法 * */ function uniq ...

  9. vue-cli 引入axios及跨域使用

    使用 cnpm 安装 axios cnpm install axios --save-dev 安装其他插件的时候,可以直接在 main.js 中引入并 Vue.use(),但是 axios 并不能 u ...

  10. 使用nginx访问FastDFS

    文中所有~~~均为同一个自定义文件夹名字,一般使用项目名称 2.1.为什么需要用Nginx访问? FastDFS通过Tracker服务器,将文件放在Storage服务器存储,但是同组存储服务器之间需要 ...