一个只能匹配非常简单的(字母 . + *)共 4 种状态的正则表达式语法的自动机(注意,仅限 DFA,没考虑 NFA):

  好久之前写的了,记得有个 bug 一直没解决...

#include <iostream>
//#include <fstream>
#include <vector>
#include <string> class DFA
{
void construction(std::string regex)
{
std::vector<AM*> worker;
Match = std::make_unique<AM>();
h = std::make_unique<AM>(toRange('H'), nullptr);
AM* h_ptr = h.get();
for (auto iter = regex.begin(); iter != regex.end(); ++iter)
{
AM * temp = new AM(toRange(*iter), h_ptr);
switch (*iter)
{
case '.':
{
h_ptr->next[temp->ch] = temp;
h_ptr = temp;
if (iter + 1 != regex.end() && *(iter + 1) != '*')
{
while (!worker.empty())
{
AM*c_ptr = worker.front();
worker.erase(worker.begin());
c_ptr->next[h_ptr->ch] = h_ptr;
}
}
}
break;
case '*':
{
h_ptr->next[h_ptr->ch] = h_ptr;
for (std::vector<AM*>::iterator i = worker.begin(); i != worker.end(); i++)
(*i)->next[h_ptr->ch] = h_ptr;
if (h_ptr->prev != nullptr)
worker.push_back(h_ptr->prev);
worker.push_back(h_ptr);
delete temp;
temp = nullptr;
}
break;
case '+':
{
h_ptr->next[h_ptr->ch] = h_ptr;
while (!worker.empty())
{
AM*c_ptr = worker.front();
worker.erase(worker.begin());
c_ptr->next[h_ptr->ch] = h_ptr;
}
delete temp;
temp = nullptr;
}
break;
default:
{
h_ptr->next[temp->ch] = temp;
h_ptr = temp;
if (iter + 1 != regex.end() && *(iter + 1) != '*')
{
while (!worker.empty())
{
AM*c_ptr = worker.front();
worker.erase(worker.begin());
c_ptr->next[h_ptr->ch] = h_ptr;
}
}
}
break;
}
}
while (!worker.empty())
{
AM*c_ptr = worker.front();
worker.erase(worker.begin());
if (h_ptr->next[h_ptr->ch] == h_ptr)
c_ptr->next[0] = Match.get();
else
c_ptr->next[h_ptr->ch] = h_ptr;
}
h_ptr->next[0] = Match.get();
} char toRange(char c) const
{
if (c == '.')
return 27;
return c - 'a' + 1;
} public:
bool isMatch(std::string s, std::string regex)
{
construction(regex);
AM * am = h.release();
for (auto i:s)
{
char c = toRange(i);
if (am == nullptr)
return false;
if (am->next[c] != nullptr)
am = am->next[c];
else if (am->next[27] != nullptr)
am = am->next[27];
else
am = am->next[c];
}
return am != nullptr && am->next[0] == Match.get();
} private:
struct AM {
char ch;
AM *prev, *next[28];
AM() : ch(), prev(), next() {}
AM(char v, AM * prev) : ch(v), prev(prev), next() {}
}; std::unique_ptr<AM> Match, h;
}; int main(int argc, char const *argv[])
{
DFA s; std::cout << (s.isMatch("abc", "aa*b*c+p*") ? "true":"false"); return 0;
}

  示例1:a*b*c+d*

  该正则表达式的DFA如下图

  示例2:(a|b)*a

  这是一个NFA,我的代码并没有实现NFA转DFA,因而会导致匹配失败。(2020-04-05 21:00:39 补充:所以 leetcode 上 a*a 过不了,因为它也是NFA。虽然可以转换为正则表达式 a+ 来匹配,它的构造图:

  但 a+ 的 DFA 构造图也可以是这样的:

  实际上我们写出状态转移表,然后直接查状态表效率会更高,不过我个人觉得模拟匹配的过程更有意思。

DFA 简易正则表达式匹配的更多相关文章

  1. [No0000100]正则表达式匹配解析过程分析(正则表达式匹配原理)&regexbuddy使用&正则优化

    常见正则表达式引擎引擎决定了正则表达式匹配方法及内部搜索过程,了解它至关重要的.目前主要流行引擎有:DFA,NFA两种引擎. 引擎 区别点 DFA Deterministic finite autom ...

  2. 正则表达式匹配可以更快更简单 (but is slow in Java, Perl, PHP, Python, Ruby, ...)

    source: https://swtch.com/~rsc/regexp/regexp1.html translated by trav, travmymail@gmail.com 引言 下图是两种 ...

  3. leetcode 10 Regular Expression Matching(简单正则表达式匹配)

    最近代码写的少了,而leetcode一直想做一个python,c/c++解题报告的专题,c/c++一直是我非常喜欢的,c语言编程练习的重要性体现在linux内核编程以及一些大公司算法上机的要求,pyt ...

  4. [LeetCode] Regular Expression Matching 正则表达式匹配

    Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...

  5. 正则表达式匹配/data/misc/wifi/wpa_supplicant.conf的WiFi名称与密码

    正则表达式匹配/data/misc/wifi/wpa_supplicant.conf的WiFi名称与密码: String regex_name="ssid=\"(.*?)\&quo ...

  6. 在Visual Studio中使用正则表达式匹配换行和批量替换

    系统环境:Windows 8.1 Enterprise Update 2 x64 开发环境:Mircosoft Visual Studio Ultimate 2013 Update 2 RC 问题:如 ...

  7. .NET正则表达式匹配Silverlight

    这是一个.NET正则表达式匹配工具的Silverlight 在页面中加入以下代码就可以了: <"> <param name="source" value ...

  8. Flex的正则表达式匹配速度与手工代码的比较

    flex是一个词法分析器生成器,它是编译器和解释器编程人员的常用工具之一.flex的程序主要由一系列带有指令(称为动作代码)的正则表达式组成.在匹配输入时,flex会将所有的正则表达式翻译成确定性有穷 ...

  9. Java/Js下使用正则表达式匹配嵌套Html标签

    转自:http://www.jb51.net/article/24422.htm 以前写过一篇文章讲解如何使用正则表达式完美解决Html嵌套标签的匹配问题(使用正则表达式匹配嵌套Html标签),但是里 ...

随机推荐

  1. V-Box

    Not ) (VERR_NEM_NOT_AVAILABLE). VT-x is disabled in the BIOS for all CPU modes (VERR_VMX_MSR_ALL_VMX ...

  2. 中文 json_encode之后字符长度问题

    问题描述: 将某个字符串$str 进行json编码,即json_encode($str)后变成Unicode字符存入数据库,会发现中文的长度明明没有超过设置的字符长度最大值,但是却抛出字段长度过长错误 ...

  3. Dubbo的SPI机制与JDK机制的不同及原理分析

    从今天开始,将会逐步介绍关于DUbbo的有关知识.首先先简单介绍一下DUbbo的整体概述. 概述 Dubbo是SOA(面向服务架构)服务治理方案的核心框架.用于分布式调用,其重点在于分布式的治理. 简 ...

  4. Python之xlrd模块读取xls文件与报错解决

    安装 pip3 install xlrd 用法 Sheet编号从0开始 rows,colnum编号均从0开始 合并的单元格仅返回第一格内容 Sheets只能被调用一次,可获取所有sheet取idx 无 ...

  5. R语言函数化编程笔记2

    R语言函数化编程笔记2 我学过很多的编程语言,可以我写的代码很啰嗦,一定是我太懒了.或许是基础不牢地动山摇 1.为什么要学函数 函数可以简化编程语言,减少重复代码或者说面向对象的作用 2.函数 2.1 ...

  6. 牛客练习赛53 B题调和级数

    https://ac.nowcoder.com/acm/contest/1114/B 这题时间卡的比较死,多了一个快速幂的logn就过不了这题. #include<bits/stdc++.h&g ...

  7. 微信小程序:如何判断数组中的条数?

    可以<view wx:if="{{list.length == 0}}"> </view> 可以在 {{}} 内进行简单的运算,包括三元运算符.逻辑判断.算 ...

  8. php7 安装redis拓展

    配置之前应该是环境已经搭好了,phpinfo的页面可以加载出来.   使用git clone下载git上的phpredis扩展包 git clone  https://github.com/phpre ...

  9. 记录 Docker 的学习过程 (单机编排)

    容器的编排 什么是容器的编排?就是让容器有序的启动并在启动的过程加以控制 docker-compose -f bainpaiwenjian.yul up 如果编排文件为默认名称docker-compo ...

  10. BK: How to read a book 第四篇

    第四篇 阅读的最终目标 第二十章 阅读的第四个层次:主题阅读 在做主题阅读时的要求: 1. 知道:知道应该读哪些书. 在面对如此庞大的相关资料时,我们要如何决定我们要研究的主题是什么呢. 如何判断属于 ...