DFA 简易正则表达式匹配
一个只能匹配非常简单的(字母 . + *)共 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 简易正则表达式匹配的更多相关文章
- [No0000100]正则表达式匹配解析过程分析(正则表达式匹配原理)&regexbuddy使用&正则优化
常见正则表达式引擎引擎决定了正则表达式匹配方法及内部搜索过程,了解它至关重要的.目前主要流行引擎有:DFA,NFA两种引擎. 引擎 区别点 DFA Deterministic finite autom ...
- 正则表达式匹配可以更快更简单 (but is slow in Java, Perl, PHP, Python, Ruby, ...)
source: https://swtch.com/~rsc/regexp/regexp1.html translated by trav, travmymail@gmail.com 引言 下图是两种 ...
- leetcode 10 Regular Expression Matching(简单正则表达式匹配)
最近代码写的少了,而leetcode一直想做一个python,c/c++解题报告的专题,c/c++一直是我非常喜欢的,c语言编程练习的重要性体现在linux内核编程以及一些大公司算法上机的要求,pyt ...
- [LeetCode] Regular Expression Matching 正则表达式匹配
Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...
- 正则表达式匹配/data/misc/wifi/wpa_supplicant.conf的WiFi名称与密码
正则表达式匹配/data/misc/wifi/wpa_supplicant.conf的WiFi名称与密码: String regex_name="ssid=\"(.*?)\&quo ...
- 在Visual Studio中使用正则表达式匹配换行和批量替换
系统环境:Windows 8.1 Enterprise Update 2 x64 开发环境:Mircosoft Visual Studio Ultimate 2013 Update 2 RC 问题:如 ...
- .NET正则表达式匹配Silverlight
这是一个.NET正则表达式匹配工具的Silverlight 在页面中加入以下代码就可以了: <"> <param name="source" value ...
- Flex的正则表达式匹配速度与手工代码的比较
flex是一个词法分析器生成器,它是编译器和解释器编程人员的常用工具之一.flex的程序主要由一系列带有指令(称为动作代码)的正则表达式组成.在匹配输入时,flex会将所有的正则表达式翻译成确定性有穷 ...
- Java/Js下使用正则表达式匹配嵌套Html标签
转自:http://www.jb51.net/article/24422.htm 以前写过一篇文章讲解如何使用正则表达式完美解决Html嵌套标签的匹配问题(使用正则表达式匹配嵌套Html标签),但是里 ...
随机推荐
- 【Vue2.x笔记3】从源码看watch对象
初始化 function initWatch (vm: Component, watch: Object) { for (const key in watch) { const handler = w ...
- SpringBoot的应运而生
随着动态语言的流行(Ruby,Groovy,Scala,Node.js),java的开发显得格外的笨重,繁多的配置,低下的效率,复杂的部署流程以及第三方技术集成难度大.springboot应运而生,使 ...
- ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
原文:https://www.stevejgordon.co.uk/httpclientfactory-using-polly-for-transient-fault-handling发表于:2018 ...
- ZOJ 4081 Little Sub and Pascal's Triangle 题解
ZOJ 4081 Little Sub and Pascal's Triangle 题解 题意 求杨辉三角第n行(从1开始计数)有几个奇数. 考察的其实是杨辉--帕斯卡三角的性质,或者说Gould's ...
- Git仓库创建---克隆仓库---初始提交代码
1.在Git上创建仓库,添加成员,默认分支是“master”,仓库路径假设为http://192.168.1.1/root/project.git 2.在sourceTree上,点击“克隆”,输入上面 ...
- ReportViewer Win32Exception (0x80004005): 创建窗口句柄时出错
System.ComponentModel.Win32Exception (0x80004005): 创建窗口句柄时出错. 在 System.Windows.Forms.NativeWindow.Cr ...
- PIE-SDK For C++栅格数据集的读取
1.功能简介 栅格数据包含很多信息,在数据的运用中需要对数据的信息进行读取,目前PIE SDK支持多种数据格式的数据读取,下面对栅格数据格式的数据读取功能进行介绍. 2.功能实现说明 2.1 实现思路 ...
- SequoiaDB报告创建线程失败的解决办法
1.问题背景 对于分布式数据库和分布式环境,高并发和高性能压力的情况下,出现线程创建失败等等问题也是十分常见的,这时候就十分考虑数据库管理员的经验,需要能快速的定位到问题和瓶颈所在,快速解决.本文也是 ...
- 浅析ReDoS
ReDoS(Regular expression Denial of Service) 正则表达式拒绝服务攻击.开发人员使用了正则表达式来对用户输入的数据进行有效性校验, 当编写校验的正则表达式存在缺 ...
- c#字符串常用方法
一.字符串常用方法 1.IndexOf("") 如果找到字符串出现的位置则为索引位置,否则返回-1,索引从0开始 2.string Substring( int sta ...