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标签),但是里 ...
随机推荐
- mysql建立索引类型及索引建立的原则
索引类型:Unique(唯一索引,一般为主键),Normal(一般索引,普通字段,可做组合索引),索引方法:BTREE 1.选择唯一性索引 唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录 ...
- Hadoop报错:org.apache.hadoop.security.AccessControlException: Permission denied: user=xxxx
问题出现原因: 因为远程提交hadoop的任务的情况下如果,没有hadoop 的系统环境变量,就会读取当前主机的用户名,所以Hadoop集群的节点中没有该用户名的权限,所以出现的异常. 解决方法: S ...
- KVM命令--使用篇(1)
1. KVM常见使用命令: 1.1 查看命令 列出所有虚拟机 virsh list --all 显示虚拟机信息 virsh dominfo vm_name 显示虚拟机内存和cpu使用情况 virsh- ...
- python笔记06
python笔记06 数据类型 上个笔记内容补充 补充 列表 reverse,反转. v1 = [1,2,3111,32,13] print(v1) v1.reverse() print(v1) v1 ...
- SVN的使用01
关于svn的使用以及TortoiseSVN常见操作 一.关于svn介绍 在介绍之前提一下,MyEclipse项目组的建立,以及源文件夹的创建. 新建的那一栏点击other 在搜索栏中搜索Java Wo ...
- 目标检测,主要问题发展,非极大值抑制中阈值也作为参数去学习更满足end2end,最近发展趋势和主要研究思路方向
目标检测,主要问题发展,非极大值抑制中阈值也作为参数去学习更满足end2end,最近发展趋势和主要研究思路方向 待办 目标检测问题时间线 特征金字塔加滑窗 对象框推荐 回归算法回归对象框 多尺度检测 ...
- Python中matplotlib模块的简单使用
测试代码如下: # encoding:utf-8 import numpy as np import matplotlib.pyplot as plt x = np.array([1,2,3,4,5, ...
- C#关于文件的创建
若使用文件夹Directory类判断了文件夹的存在,后面的文件就不需要使用File类来判断文件的存在与否和创建,只需要在前面判断过得文件夹路径后面加上文件的名字即可,它会自动判断文件是否存在,若不存在 ...
- CF-478C Table Decorations (贪心)
Table Decorations Time limit per test: 1 second Memory limit per test: 256 megabytes Problem Descrip ...
- python面试的100题(17)
内存管理与垃圾回收机制 48.哪些操作会导致Python内存溢出,怎么处理? 内存溢出:你申请了10个字节的内存,但写入了大于10个字节的数据会导致内存溢出 内存溢出原因:1.内存中加载的数据量过于庞 ...