写个简单的正则表达式

使用NFA来构造正则表达式,详细解释可以参见Algorithm 4th。书中代码为JAVA版本。

书中内容前后耦合度较大,遂用cpp简单的实现了一下(基于vector的存储方式主要是我发现std::stack不能访问中间的元素,性能上的优化我就忽略掉了)。

代码接受“(A*C|AB)V.*”等类似的正则表达式,不检测中间匹配的情况(主要是为了缩减代码量,我对200这个数很纠结)

由于判断检测成功的方式特别简单(这样好写),正则式需要去掉最外面的括号“(A.*)”是不允许的,“A.*”可以。

  1 #include<iostream>
  2 #include<stack>
  3 #include<vector>
  4 #include<memory>
  5 using namespace std;
  6
  7 struct Node
  8 {
  9     char charValue;
 10     vector<int> nextIndices;
 11 };
 12 class LinkGraph
 13 {
 14 public:
 15     LinkGraph(std::string str)
 16     {
 17         for(int i=0;i<(int)str.size();i++)
 18         {
 19             Node node;
 20             node.charValue = str[i];
 21             nodes.push_back(node);
 22         }
 23     }
 24     bool AddEdge(int i,int j)
 25     {
 26         if(i>=nodes.size()||j>=nodes.size())
 27         return false;
 28         //cheack duplicate node
 29         for(int k=0;k<nodes[i].nextIndices.size();k++)
 30             if(nodes[i].nextIndices[k]==j)
 31                 return false;
 32         nodes[i].nextIndices.push_back(j);
 33         return true;
 34     }
 35     void Print()
 36     {
 37         for(int i=0;i<nodes.size();i++)
 38         {
 39             std::cout<<i<<":";
 40             for(int j=0;j<nodes[i].nextIndices.size();j++)
 41                 std::cout<<"->"<<nodes[i].nextIndices[j];
 42             std::cout<<std::endl;
 43         }
 44     }
 45     const Node& GetNode(int index)
 46     {
 47         if(index<nodes.size())
 48             return nodes[index];
 49
 50         throw "Index Out Of Range";
 51     }
 52     int GetNodesSize()
 53     {
 54         return nodes.size();
 55     }
 56 private:
 57     vector<Node> nodes;
 58 };
 59 class NFA
 60 {
 61 public:
 62     NFA(std::string str)
 63     {
 64
 65         TestString=‘(‘+str+‘)‘;
 66         graph=new LinkGraph(TestString);
 67         ComposeGraph(TestString);
 68     }
 69
 70     void ComposeGraph(std::string TestString)
 71     {
 72         std::stack<int> ops;
 73         for(int i=0;i<TestString.size();i++)
 74         {
 75             char CurChar=TestString[i];
 76             int lp=i;
 77             if(CurChar==‘|‘||CurChar==‘(‘)
 78                 ops.push(i);
 79             else if(CurChar==‘)‘)
 80             {
 81                 //int or = (int)ops.top();
 82                 int orValue = (int)ops.top();
 83                 if(TestString[orValue]==‘|‘)//or
 84                 {
 85                     graph->AddEdge(orValue,i);
 86                     ops.pop();//pop ‘|‘
 87                     lp = ops.top();
 88                     graph->AddEdge(lp,orValue+1);
 89                     ops.pop();//pop ‘(‘
 90                 }
 91                 else
 92                 {
 93                     lp=orValue;
 94                     ops.pop();//pop ‘(‘
 95                 }
 96             }
 97
 98             if(i<TestString.size()-1&&TestString[i+1]==‘*‘)
 99             {
100                 graph->AddEdge(i+1,lp);
101                 graph->AddEdge(lp,i+1);
102             }
103
104             if(CurChar==‘(‘||CurChar==‘)‘||CurChar==‘*‘)
105                 graph->AddEdge(i,i+1);
106
107         }
108     }
109     void fillVector(vector<int>& v,int index)
110     {
111         v.push_back(index);
112         for(int i=0;i<graph->GetNode(index).nextIndices.size();i++)
113         {
114             bool contain = false;
115             for(int j=0;j<v.size();j++)
116                 if(v[j]==graph->GetNode(index).nextIndices[i])
117                 {
118                     contain = true;
119                     break;
120                 }
121             if(!contain)
122             fillVector(v,graph->GetNode(index).nextIndices[i]);
123         }
124
125     }
126     void initVector(vector<int>& v,int index)
127     {
128         v.clear();
129         fillVector(v,index);
130     }
131     void PrintVector(const vector<int>& v)
132     {
133         for(int i=0;i<v.size();i++)
134         std::cout<<v[i]<<" ";
135         std::cout<<std::endl;
136     }
137     bool RecognizeText(std::string str)
138     {
139         vector<int> potentialIndex;
140         //init
141         initVector(potentialIndex,0);
142         PrintVector(potentialIndex);
143         //test
144         int strIndex=0;
145         vector<int> passedIndex;
146         int NFAMaxIndex=0;
147         while(potentialIndex.size()&&strIndex<str.size())
148         {
149             for(int i=0;i<potentialIndex.size();i++)
150                 if(TestString[potentialIndex[i]]==str[strIndex]||
151                 TestString[potentialIndex[i]]==‘.‘)
152                 {
153                     passedIndex.push_back(potentialIndex[i]+1);
154                 }
155
156             if(passedIndex.size()==0)
157                 //return false;
158                 //return strIndex==str.size();
159                 break;//return NFAMaxIndex==TestString.size()-1;
160             strIndex++;
161             potentialIndex.clear();
162             PrintVector(passedIndex);
163             for(int k=0;k<passedIndex.size();k++)
164                 fillVector(potentialIndex,passedIndex[k]);
165             for(int k=0;k<potentialIndex.size();k++)
166                 if(potentialIndex[k]>NFAMaxIndex)
167                     NFAMaxIndex = potentialIndex[k];
168             passedIndex.clear();
169             PrintVector(potentialIndex);
170         }
171         PrintVector(potentialIndex);
172         std::cout<<"maxIndex="<<NFAMaxIndex;
173         return NFAMaxIndex>=TestString.size()-1;
174     }
175     ~NFA()
176     {
177         if(graph)
178         delete graph;
179     }
180     void Print()
181     {
182         graph->Print();
183     }
184 private:
185     LinkGraph* graph;
186     std::string TestString;
187 };
188 int main()
189 {
190 //    std::auto_ptr<LinkGraph> graph (new LinkGraph("abcd"));
191 //     graph->AddEdge(0,1);
192 //     graph->AddEdge(0,1);
193 //     graph->Print();
194     std::auto_ptr<NFA> nfa(new NFA(std::string("(A*B|AC)D")));
195     nfa->Print();
196     bool result = nfa->RecognizeText(std::string("AABD"));
197     std::cout<<"\nIs this string ACCEPTED?  \n "<<(result?"Accepted":"Didn‘t Match")<<std::endl;
198     return 0;
199 }

200行,恩。200。

时间: 2024-10-14 19:41:18

写个简单的正则表达式的相关文章

也写一个简单的网络爬虫

引子 在cnblogs也混了许久,不过碍于平日工作太忙,一篇随笔也没有写过.最近经常感觉到自己曾经积累过的经验逐步的丢失,于是开通了博客,主要是记录一下自己在业余时间里玩的一些东西. 缘起 言归正传.某次在在某高校网站闲逛,看到了一些有趣的东西想要保存起来,但是却分散在各个页面,难以下手.使用baidu,google却有无法避免的搜索到此站点之外的内容.于是就想如果有一个爬虫,可以抓取指定域名的某些感兴趣的内容,不是很好.在网上简单搜索了一下,简单的都不满意,功能强大的又太复杂,就想自己写一个.

分享一个近期写的简单版的网页采集器

分享一个近期写的简单版的网页采集器 功能特点: 1.可通过配置,保存采集规则. 2.可通过采集规则,进行数据采集. 3.可分页,分关键字,进行采集. 4.可保存数据至数据库,文本中. ........... 功能还比较简单,喜欢深入的可以继续深入下去,暂时还没有登录的功能,因为登录功能涉及到的范围比较广,待日后慢慢研究后再开发. 我先上个图让大家一睹为快吧: 首先看看页面,我们要采集这个网站的文章 接下来,首先是查找分页,获得分页里面的文章链接,接着查找内容页需要采集的字段,生成规则,进行采集.

linux设备驱动第三篇:写一个简单的字符设备驱动

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存. 下面就开始学习如何写一个简单的字符设备驱动.首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作. 1.主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的.他们通常位于/dev目录下.如下: [plain] vie

用C#Winform写个简单的批量清空文件内容和删除文件的小工具

用C#Winform写个简单的批量清空文件内容和删除文件的小工具 本文介绍这个简单得不能再简单的小项目.做这个项目,有以下目的. 1 当然是做个能用的工具 2 学习使用Github 关于用VS2013创建一个项目并添加到Github的教程,请参考(http://www.admin10000.com/document/4004.html).简单来说,就是先用VS创建项目:然后在Github网站上创建一个Respo(本项目的代码托管项目),记下(https://*.git)那个地址:最后用"提交&q

(2)自己写一个简单的servle容器

自己写一个简单的servlet,能够跑一个简单的servlet,说明一下逻辑. 首先是写一个简单的servlet,这就关联到javax.servlet和javax.servlet.http这两个包的类,其中一个比较重要的接口就是:javax.servlet.Servlet,所有的servlet必须实现实现或者继承实现该接口的类. Servlet接口有五个方法: public void init(ServletConfig config) throws ServletException publi

ASP.NET 使用application和session对象写的简单聊天室程序

ASP.Net中有两个重要的对象,一个是application对象,一个是session对象. Application:记录应用程序参数的对象,该对象用于共享应用程序级信息. Session:记录浏览器端的变量对象,用来存储跨网页程序程序的变量或者对象. 说实话,写了快一年的asp.net,application对象还真没怎么用过.看了看书,根据这两个对象的特性写了一个简单的聊天室程序.真的是非常的简陋. 我的思路是,有两个页面Default页和ChatRoom页,页面布局如图: Default

Swift 写一个简单界面(实战-新手)

原文链接 在这篇博文中你可以看到那些内容呢, 首先这是一个用tableView纯代码Swift写的简单界面, 你可以看到下面这些 - 使用Alamofire 进行网络请求 - 使用MJExtension 进行字典转模型 - 使用HanekeSwift 进行图片的赋值 - 如何写一个模型(M) - 如何自定义一个UITableViewCell Alamofire 简单网络请求 func XTNetworkReq(url: String){ print("SUMMER_TEST_1") A

分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业不是百度来的,我只是百度了一些示例代码的意思,怎么用!算了,越解释万一越黑呢!哈哈O(∩_∩)O哈哈~) ----------------------------------------------------------------分界线------------------------------

Java写一个简单学生管理系统

其实作为一名Java的程序猿,无论你是初学也好,大神也罢,学生管理系统一直都是一个非常好的例子,初学者主要是用数组.List等等来写出一个简易的学生管理系统,二.牛逼一点的大神则用数据库+swing来做一个有界面的学生管理系统.其实都并不会太难. 今天我就先写一个简单的用List来实现学生管理系统: 首先,管理系统是针对学生对象的,所以我们先把学生对象就写出来: package bean; public class Student { String name; String studentId;