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标签),但是里 ...
随机推荐
- 题解【洛谷P3456】[POI2007]GRZ-Ridges and Valleys
题面 考虑 \(\text{Flood Fill}\). 每次在 \(\text{BFS}\) 扩展的过程中增加几个判断条件,记录山峰和山谷的个数即可. #include <bits/stdc+ ...
- mysql 时间,时间戳,字符串之间相互转换
时间转字符串 date_format(now(),'%Y-%m-%d') 时间转时间戳 unix_timestamp(now()) 字符串转时间 str_to_date('2020-01-19','% ...
- P问题,NP问题,NPC问题学习笔记
参考:https://www.luogu.org/blog/styx-ferryman/chu-sai-bei-kao-gan-huo-p-wen-ti-np-wen-ti-npc-wen-ti-sh ...
- RN开发-组件View,Text
1.外联js文件(RN自定义组件) module.exports=Header; 导出模块 const Header=require('./header'); 导入外部j ...
- C/C++ Windows API——获取系统指定目录(转)
原文地址:C/C++ Windows API——获取系统指定目录 经测试,在win10 VS2017中用wprintf()输出正常,SHGetSpecialFolderPath函数也正常运行 但是用M ...
- 2020牛客寒假算法基础集训营5 G.街机争霸 (bfs)
https://ac.nowcoder.com/acm/problem/201961 预处理出僵尸走的路径,僵尸走的周期长度应该为2k-2,在普通的bfs基础上加上一维表示时间,从当前位置x,y和和时 ...
- ASP.NET Identity系列教程-1目录
https://www.cnblogs.com/hao-1234-1234/p/8857437.html ASP.NET Identity系列教程 13 Getting Started with Id ...
- 05 部署mysql关系数据库
01 安装Mysql 在官网https://dev.mysql.com/上找到自己需要的版本并执行安装 sudo apt-get install mysql-server-5.7 02 运行和退出 # ...
- 融e学 一个专注于重构知识,培养复合型人才的平台【获取考试答案_破解】
考试系统-融e学-一个专注于重构知识,培养复合型人才的平台.[获取答案] ganquanzhong 背景:今天去完成学校在融e学上开设的必修课和选修课考试,由于自己的时间有限(还有其他的事情要去做). ...
- 安全相关的Linux知识
本文用于记录在安全中的Linux常用命令,基础命令可以移步去菜鸟教程(https://www.runoob.com/linux/linux-tutorial.html)学习 Linux重要的4个热键 ...