正则表达式匹配(自动机)

自动机实现正则表达式匹配,https://leetcode.com/problems/regular-expression-matching/

这题有更简单的做法,自动机则更加通用

自动机配合hash实现NFA到DFA的转化,Compiler课里面看到很多自动机自动生成的工具,所以就写了一个简单的。

#include <bits/stdc++.h>
using namespace std;
//A program resolve RegExp contains only letters & *(no consecutive *) with len <= 30
const static int bign = 33;
const static int hashNum = 100003;
const static int charNum = 26;
const static int maxStateNum = 1033;
int mark[bign];
char valchar[bign];
int n = 0;
int stateNum = 1;

int firstend;

int stateAuto[maxStateNum][charNum];
int mq[maxStateNum];
int mfront, mtail;
vector<int> hashList[hashNum];
vector<vector<int>> stateToIndex;
vector<pair<int, int>> nxtState[bign];
bool isend[maxStateNum];
int vst[26][bign];


inline int hashCode(vector<int> &vec)
{
	int ret = 0;
	for (int v : vec)
		ret = (ret * 31 + v) % hashNum;
	return ret;
}

inline bool equalVec(vector<int>& vec1, vector<int>& vec2)
{
	if (vec1.size() != vec2.size())
		return false;
	for (int i = 0; i < vec1.size(); i++)
		if (vec1[i] != vec2[i])
			return false;
	return true;
}

void AutoCons(const char* RegExp)
{
	stateNum = 1;
	int slen = strlen(RegExp);
	
	for (int i = 0; i < slen; i++)
	{
		if (RegExp[i] == '*')
		{
			mark[n - 1] = 1;
		}
		else
		{
			valchar[n++] = RegExp[i];
		}
	}
	firstend = n;
	for (int i = n - 1; i >= 0; i--)
	{
		if (mark[i] == 0)
		{
			//firstend = i + 1;
			break;
		}
		else
		{
			firstend--;
		}
	}
	for (int i = n - 1; i >= 0; i--)
	{
		if (valchar[i] == '.')
		{
			for (int j = 0; j < 26; j++)
			{
				if (1 == mark[i])
				{
					nxtState[i].push_back(make_pair(j, i));
					vst[j][i] = i + 1;
				}
				nxtState[i].push_back(make_pair(j, i + 1));
				vst[j][i + 1] = i + 1;
			}
		}
		else
		{
			if (1 == mark[i])
			{
				vst[valchar[i] - 'a'][i] = i + 1;
				nxtState[i].push_back(make_pair(valchar[i] - 'a', i));
			}
			vst[valchar[i] - 'a'][i + 1] = i + 1;
			nxtState[i].push_back(make_pair(valchar[i] - 'a', i + 1));
		}
		if (1 == mark[i])
		{
			for (auto it : nxtState[i + 1])
			{
				if(vst[it.first][it.second] != i + 1)
					nxtState[i].push_back(it);
			}
		}
		//sort(nxtState[i].begin(), nxtState[i].end());
		//unique(nxtState[i].begin(), nxtState[i].end());
	}
	vector<int> state1(1, 0);
	if (firstend == 0)
		isend[1] = true;
	for (int i = 0; i < n; i++)
	{
		if (1 == mark[i])
		{
			state1.push_back(i + 1);
			if(firstend <= i + 1)
				isend[1] = true;
		}
		else
			break;
	}
	stateToIndex.push_back(state1);
	hashList[hashCode(state1)].push_back(1);

	mq[mtail++] = stateNum;
	memset(vst, 0, sizeof(vst));
	while (mfront < mtail)
	{
		int u = mq[mfront++];
		//u--;
		vector<int> tvec[26];
		for(int i = 0; i < 26; i++)
			tvec[i].clear();
		
		for (int i = 0; i < stateToIndex[u - 1].size(); i++)
		{
			for (pair<int, int> tautomata : nxtState[stateToIndex[u - 1][i]])
			{
				int x = tautomata.first;
				int y = tautomata.second;
				if (vst[x][y] != u)
					vst[x][y] = u;
				else
					continue;
				tvec[x].push_back(y);
				//if (tautomata.second >= firstend)
				//	endflag = true;
			}
		}
		
		for (int i = 0; i < 26; i++)
		{
			if (tvec[i].empty())
				continue;
		//	sort(tvec[i].begin(), tvec[i].end());
		//	unique(tvec[i].begin(), tvec[i].end());
			int hashnum = hashCode(tvec[i]);
			bool flag = false;
			for (int stateid : hashList[hashnum])
			{
				if (equalVec(stateToIndex[stateid - 1], tvec[i]))
				{
					flag = true;
					stateAuto[u][i] = stateid;
					break;
				}
			}
			if (!flag)
			{
				stateNum++;
				stateAuto[u][i] = stateNum;
				hashList[hashnum].push_back(stateNum);
				stateToIndex.push_back(tvec[i]);
				mq[mtail++] = stateNum;
				if (tvec[i][tvec[i].size() - 1] >= firstend)
					isend[stateNum] = true;
			}
		}
	}
	cout << "stateNum of DFA = " << stateNum << endl;
}

bool mMatch(const char* matchstr)
{
	int slen = strlen(matchstr);
	int nowstate = 1;
	for (int i = 0; i < slen; i++)
	{
		int tc = matchstr[i] - 'a';
		nowstate = stateAuto[nowstate][tc];
		if (0 == nowstate)
		{
			return false;
		}
		//if (isend[nowstate])
		//	return true;
	}
	return isend[nowstate];
}

int main()
{
	//"bbbba"
	//	".*a*a"
	string p = ".*a*a";
	string s = "bbbba";
	AutoCons(p.c_str());

	if (mMatch(s.c_str()))
		cout << "matching successfully" << endl;
	else
		cout << "matching failed" << endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
正则表达式自动生成器是一个智能、易用的正则表达式生成、测试以及字符串提取工具。正则表达式库让你可以直接借用正则表达式,而无需自己费脑筋。“正则表达式自动生成器”可以自动生成正则表达式,测试正则表达式,可视化显示结果,导出提取字符串,你所要做的,仅仅是几下鼠标点击! 正则表达式自动生成器主要功能: 自动生成正则表达式 编辑并测试正则表达式 多向导页,可在多个源文本上测试同一个正则表达式(标准版无此功能) 多页参考生成正则表达式(标准版无此功能) 自动检查和修改生成正则表达式的正确性 以可视方式呈现测试结果 从文本文件中获取源文本 从HTML页面中获取源代码 一键导出匹配文本 一键导出提取字符组,并按自定义的分隔符进行分隔 保存项目以便重复测试和修改 在“设计元素”中学习并创建正则表达式 直接从正则表达式库中选择利用正则表达式 多语种 100%-200%大字体下完美显示 你可以从任何纯文本中提取有规律的文字,比如txt文件,XML文件,csv文件,HTML文件等,然后导出到剪贴板或文本文件中,你可以很方便地把它们导入到程序,数据库,excel文件等。 正则表达式自动生成器现在有三个语言版本: 英语,简体中文,繁体中文,我们会在以后加入其他语言,比如日语,德语和法语等。 正则表达式自动生成器更新内容: 1、修复一些小bug。 2、增加自定义组和限定词的正则表达式 3、增加自定义窗口背景 4、增加自定义按钮背景 5、修改软件时间为UTC时间(日志除外) 6、修改更新模块 正则表达式自动生成器截图:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值