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标签),但是里 ...
随机推荐
- nginx 配置 强制访问https
使用nginx的301状态码 server { listen ; if ($scheme = 'http') { return 301 https://$server_name$requ ...
- BZOJ3473&&BZOJ3277串
BZOJ3473&&BZOJ3277串 题面 自己找去 HINT 对于所有串建立一个广义后缀自动机,对于每一个节点开一个set表示这个节点接受的子串在哪些串里出现过,然后在parent ...
- C++->List的使用注释
List容器的应用: //----------单链队列-------队列的链式存储结构--------------- typedef struct QNode{ ...
- 原生js判断设备类型
var u = navigator.userAgent; //Android终端 var isAndroid = u.indexOf('Android') > -1 || u.indexOf(' ...
- 倍加福r2000激光驱动安装及使用
第一次完成激光的驱动安装和激光数据的采集,遇到很多问题,最后一一解决,现在记录下来,方便后面給机器人安装激光使用 激光的了解 (1)激光型号:OMD30M-R2000(30M表示30m) (2)参考手 ...
- 多线程启动selenium,报NameError: name '__file__' is not defined
将__file__加上单引号就解决了: # 获取当前文件名,用于创建模型及结果文件的目录 file_name = os.path.basename('__file__').split('.') ...
- PP: Multi-Horizon Time Series Forecasting with Temporal Attention Learning
Problem: multi-horizon probabilistic forecasting tasks; Propose an end-to-end framework for multi-ho ...
- phpstorm实现分屏展示代码
第一种 选择你要分屏的页面 [Window]—>[Editor Tabs]—>[Split Vertically]or[Split Horizontally] 第二种 把鼠标箭头放到你想 ...
- (转)git fetch + merge 和 git pull 的区别
转自:http://blog.csdn.net/a19881029/article/details/42245955 Git fetch和git pull都可以用来更新本地库,它们之间有什么区别呢? ...
- zabbix4.4.2安装部署
1.下载阿里的源,执行 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 2 ...