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

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

  1. #include <iostream>
  2. //#include <fstream>
  3. #include <vector>
  4. #include <string>
  5.  
  6. class DFA
  7. {
  8. void construction(std::string regex)
  9. {
  10. std::vector<AM*> worker;
  11. Match = std::make_unique<AM>();
  12. h = std::make_unique<AM>(toRange('H'), nullptr);
  13. AM* h_ptr = h.get();
  14. for (auto iter = regex.begin(); iter != regex.end(); ++iter)
  15. {
  16. AM * temp = new AM(toRange(*iter), h_ptr);
  17. switch (*iter)
  18. {
  19. case '.':
  20. {
  21. h_ptr->next[temp->ch] = temp;
  22. h_ptr = temp;
  23. if (iter + 1 != regex.end() && *(iter + 1) != '*')
  24. {
  25. while (!worker.empty())
  26. {
  27. AM*c_ptr = worker.front();
  28. worker.erase(worker.begin());
  29. c_ptr->next[h_ptr->ch] = h_ptr;
  30. }
  31. }
  32. }
  33. break;
  34. case '*':
  35. {
  36. h_ptr->next[h_ptr->ch] = h_ptr;
  37. for (std::vector<AM*>::iterator i = worker.begin(); i != worker.end(); i++)
  38. (*i)->next[h_ptr->ch] = h_ptr;
  39. if (h_ptr->prev != nullptr)
  40. worker.push_back(h_ptr->prev);
  41. worker.push_back(h_ptr);
  42. delete temp;
  43. temp = nullptr;
  44. }
  45. break;
  46. case '+':
  47. {
  48. h_ptr->next[h_ptr->ch] = h_ptr;
  49. while (!worker.empty())
  50. {
  51. AM*c_ptr = worker.front();
  52. worker.erase(worker.begin());
  53. c_ptr->next[h_ptr->ch] = h_ptr;
  54. }
  55. delete temp;
  56. temp = nullptr;
  57. }
  58. break;
  59. default:
  60. {
  61. h_ptr->next[temp->ch] = temp;
  62. h_ptr = temp;
  63. if (iter + 1 != regex.end() && *(iter + 1) != '*')
  64. {
  65. while (!worker.empty())
  66. {
  67. AM*c_ptr = worker.front();
  68. worker.erase(worker.begin());
  69. c_ptr->next[h_ptr->ch] = h_ptr;
  70. }
  71. }
  72. }
  73. break;
  74. }
  75. }
  76. while (!worker.empty())
  77. {
  78. AM*c_ptr = worker.front();
  79. worker.erase(worker.begin());
  80. if (h_ptr->next[h_ptr->ch] == h_ptr)
  81. c_ptr->next[0] = Match.get();
  82. else
  83. c_ptr->next[h_ptr->ch] = h_ptr;
  84. }
  85. h_ptr->next[0] = Match.get();
  86. }
  87.  
  88. char toRange(char c) const
  89. {
  90. if (c == '.')
  91. return 27;
  92. return c - 'a' + 1;
  93. }
  94.  
  95. public:
  96. bool isMatch(std::string s, std::string regex)
  97. {
  98. construction(regex);
  99. AM * am = h.release();
  100. for (auto i:s)
  101. {
  102. char c = toRange(i);
  103. if (am == nullptr)
  104. return false;
  105. if (am->next[c] != nullptr)
  106. am = am->next[c];
  107. else if (am->next[27] != nullptr)
  108. am = am->next[27];
  109. else
  110. am = am->next[c];
  111. }
  112. return am != nullptr && am->next[0] == Match.get();
  113. }
  114.  
  115. private:
  116. struct AM {
  117. char ch;
  118. AM *prev, *next[28];
  119. AM() : ch(), prev(), next() {}
  120. AM(char v, AM * prev) : ch(v), prev(prev), next() {}
  121. };
  122.  
  123. std::unique_ptr<AM> Match, h;
  124. };
  125.  
  126. int main(int argc, char const *argv[])
  127. {
  128. DFA s;
  129.  
  130. std::cout << (s.isMatch("abc", "aa*b*c+p*") ? "true":"false");
  131.  
  132. return 0;
  133. }

  示例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. PIE-SDK For C++矢量数据空间索引的创建

    1.功能简介 空间索引的使用便于数据的查询:所以在创建矢量数据的时候创建空间索引,下面对矢量数据如何创建空间索引进行功能介绍. 2.功能实现说明 2.1 实现思路及原理说明 第一步 创建矢量要素数据集 ...

  2. ArcScene 创建三维模型数据

    1. 拉伸 添加面元素图层 在图层上右键----属性 , 设置拉伸值,可以输入固定值或者选择字段值. 2. 导入   3DMAX 的 3ds 文件,和 Google SketchUp 的skp文件, ...

  3. css实现梯形样式(含有border)

    类似本文热门评论 效果 .hot-comment-title{ float:right; position:absolute; right: -8px; top: -30px; padding: 0; ...

  4. 洛谷P1308 统计单词数

    原题链接:https://www.luogu.org/problem/P1308 #include<iostream> #include<cstring> #include&l ...

  5. 微信小程序weui的使用

    大家好,我是前端菜鸟,大家可以叫我惊蛰,今天给大家分享一下在微信小程序中对weui的引入和使用,其他的也不再赘述,文中有不对的还请指正,谢谢. 直入主题: 1.下载weui 进入GitHub http ...

  6. vue formatter element表格处理数据

    formatter 指定一个vue methods 方法 作用:对从数据库中取出的数据进行处理后展示. <el-table-column prop="partner1" // ...

  7. C++面向对象编程实例

    实例一.四位运算符操作 main.cpp. #include <iostream> #include "operator_1.h" #include <stdio ...

  8. Java面向对象--类和对象

    面向对象是相对于面向过程而言的,是软件开发方法.面向对象把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统设计,更贴近事物的自然运行模式.本篇博客介绍Java面向对象的类和对象 目录: 面 ...

  9. 条件锁Condition

    """设计场景:timo先说一句,亚索再说一句timo: timo队长正在待命yasuo: 面对疾风吧timo: timo整装待发yasuo: 哈杀gay "& ...

  10. HTML连载63-a标签的伪类选择器

    一.a标签的伪类选择器 1.通过观察可以发现a标签存在一定状态 (1)默认状态,从未被访问过 (2)被访问过的状态 (3)鼠标长按的状态 (4)鼠标悬停在a标签上的演示 2.什么是a标签的伪类选择器? ...