NFA的确定化

news2024/11/28 18:41:37

一、实验目的

(1)通过本次实验,加深对正则表达式、NFA、DFA及其识别的语言的理解;
(2)掌握从NFA到DFA的转换,以及用子集法把NFA转换成DFA理论,编程实现将NFA(不确定有穷自动机)转换为DFA(确定有穷自动机)。

二、实验内容

将给定的NFA进行确定化,输出等价的DFA。要求选择合适的NFA的存储格式,并进行正确性检查。

三、实验原理

(1)NFA
NFA(nondeterministic finite-state automata)即非确定有限自动机, 一个非确定的有限自动机NFA M’是一个五元式:

NFA M’=(S, Σ∪{ε}, δ, S0, F)
其中 S—有限状态集
Σ∪{ε}—输入符号加上ε,即自动机的每个结点所射出的弧可以是Σ中一个字符或是ε。
S0—初态集 F—终态集
δ—转换函数 S×Σ∪{ε} →2S
(2S --S的幂集—S的子集构成的集合)

(2)DFA
DFA(deterministic finite-state automata)即确定有限自动机,一个确定的有限自动机DFA M是一个五元式:

M=(S, Σ,δ, S0, Z) 其中:
S —有限状态集
Σ—输入字母表
δ—映射函数(也称状态转换函数)
S×Σ→S
δ(s,a)=S’, S, S’ ∈S, a∈Σ
S0 —初始状态 S0 ∈S
Z—终止状态集 Z S

(3)NFA和DFA之间的联系
在非确定的有限自动机NFA中,由于某些状态的转移需从若干个可能的后续状态中进行选择,故一个NFA对符号串的识别就必然是一个试探的过程。这种不确定性给识别过程带来的反复,无疑会影响到FA的工作效率。而DFA则是确定的,将NFA转化为DFA将大大提高工作效率,因此将NFA转化为DFA是有其一定必要的。

四、实验结果

在这里插入图片描述

五、代码实现

#include<iostream>
#include<string>
#define MAXS 100
using namespace std;
string NODE;//结点集合
string CHANGE;//终结符集合
int N;//NFA边数
struct edge
{
	string first;
	string change;
	string last;
};
struct chan
{
	string ltab;
	string jihe[MAXS];
};
void kong(int a)
{
	int i;
	for (i = 0; i < a; i++)
		cout << ' ';
}
//排序
void paixu(string &a)
{
	int i, j;
	char b;
	for (j = 0; j < a.length(); j++) {
		for (i = 0; i < a.length(); i++) {
			if (NODE.find(a[i]) > NODE.find(a[i + 1]))
			{
				b = a[i];
				a[i] = a[i + 1];
				a[i + 1] = b;
			}
		}
	}
}

void eclouse(char c, string &he, edge b[])
{
	int k;
	for (k = 0; k < N; k++)
	{
		if (c == b[k].first[0])
			if (b[k].change == "*")
			{
				if (he.find(b[k].last) > he.length())
					he += b[k].last;
				eclouse(b[k].last[0], he, b);
			}
	}
}

void move(chan &he, int m, edge b[])
{
	int i, j, k, l;
	k = he.ltab.length();
	l = he.jihe[m].length();
	for (i = 0; i < k; i++)
		for (j = 0; j < N; j++)
			if ((CHANGE[m] == b[j].change[0]) && (he.ltab[i] == b[j].first[0]))
				if (he.jihe[m].find(b[j].last[0]) > he.jihe[m].length())
					he.jihe[m] += b[j].last[0];
	for (i = 0; i < l; i++)
		for (j = 0; j < N; j++)
			if ((CHANGE[m] == b[j].change[0]) && (he.jihe[m][i] == b[j].first[0]))
				if (he.jihe[m].find(b[j].last[0]) > he.jihe[m].length())
					he.jihe[m] += b[j].last[0];
}
//输出
void outputfa(int len, int h, chan *t)
{
	int i, j, m;
	cout << " I ";
	for (i = 0; i < len; i++)
		cout << 'I' << CHANGE[i] << " ";
	cout << endl << "-------------------------" << endl;
	for (i = 0; i < h; i++)
	{
		cout << ' ' << t[i].ltab;
		m = t[i].ltab.length();
		for (j = 0; j < len; j++)
		{
			kong(8 - m);
			m = t[i].jihe[j].length();
			cout << t[i].jihe[j];
		}
		cout << endl;
	}
}
int main()
{
	edge *b = new edge[MAXS];
	int i, j, k, m, n, h, x, y, len;
	bool flag;
	string jh[MAXS], endnode, ednode, sta;
	cout << "请输入NFA各边信息(起点条件[空为*] 终点),以#结束:" << endl;
	for (i = 0; i < MAXS; i++)
	{
		cin >> b[i].first;
		if (b[i].first == "#")
			break;
		cin >> b[i].change >> b[i].last;
	}
	N = i;
	/*for(j=0;j<N;j++)
	cout<<b[j].first<<b[j].change<<b[j].last<<endl;*/
	for (i = 0; i < N; i++)
	{
		if (NODE.find(b[i].first) > NODE.length())
			NODE += b[i].first;
		if (NODE.find(b[i].last) > NODE.length())
			NODE += b[i].last;
		if ((CHANGE.find(b[i].change) > CHANGE.length()) && (b[i].change != "*"))
			CHANGE += b[i].change;
	}
	len = CHANGE.length();
	cout << "结点中属于终态的是:" << endl;
	cin >> endnode;
	for (i = 0; i < endnode.length(); i++)
		if (NODE.find(endnode[i]) > NODE.length())
		{
			cout << "所输终态不在集合中,错误!" << endl;
			return 0;
		}
	//cout<<"endnode="<<endnode<<endl;
	chan *t = new chan[MAXS];
	t[0].ltab = b[0].first;
	h = 1;
	eclouse(b[0].first[0], t[0].ltab, b);//求e-clouse
	//cout<<t[0].ltab<<endl;
	for (i = 0; i < h; i++)
	{
		for (j = 0; j < t[i].ltab.length(); j++)
			for (m = 0; m < len; m++)
				eclouse(t[i].ltab[j], t[i].jihe[m], b);//求e-clouse
		for (k = 0; k < len; k++)
		{
			//cout<<t[i].jihe[k]<<"->";
			move(t[i], k, b);//求move(I,a)
			//cout<<t[i].jihe[k]<<endl;
			for (j = 0; j < t[i].jihe[k].length(); j++)
				eclouse(t[i].jihe[k][j], t[i].jihe[k], b);//求e-clouse
		}
		for (j = 0; j < len; j++)
		{
			paixu(t[i].jihe[j]);//对集合排序以便比较
			for (k = 0; k < h; k++)
			{
				flag = operator==(t[k].ltab, t[i].jihe[j]);
				if (flag)
					break;
			}
			if (!flag&&t[i].jihe[j].length())
				t[h++].ltab = t[i].jihe[j];
		}
	}
	cout << endl << "状态转换矩阵如下:" << endl;
	outputfa(len, h, t);//输出状态转换矩阵
	//状态重新命名
	string *d = new string[h];
	NODE.erase();
	cout << endl << "重命名:" << endl;
	for (i = 0; i < h; i++)
	{
		sta = t[i].ltab;
		t[i].ltab.erase();
		t[i].ltab = 'A' + i;
		NODE += t[i].ltab;
		cout << '{' << sta << "}=" << t[i].ltab << endl;
		for (j = 0; j < endnode.length(); j++) {
			if (sta.find(endnode[j]) < sta.length())
				d[1] = ednode += t[i].ltab;
		}
		for (k = 0; k < h; k++) {
			for (m = 0; m < len; m++) {
				if (sta == t[k].jihe[m])
					t[k].jihe[m] = t[i].ltab;
			}
		}
	}
	for (i = 0; i < NODE.length(); i++) {
		if (ednode.find(NODE[i]) > ednode.length())
			d[0] += NODE[i];
	}
	endnode = ednode;
	cout << endl << "DFA如下:" << endl;
	outputfa(len, h, t);
	//输出DFA
	cout << "其中终态为:" << endnode << endl;//DFA最小化 
	system("pause");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP 事务代码BD20不能处理状态为51的IDoc

SAP 事务代码BD20不能处理状态为51的IDoc 对于SAP IDoc相关的事务代码比如WE02,WE19,BD87等都比较熟悉&#xff0c;因为使用的比较多。但是对于事务代码BD20却很少使用。 笔者在近期的一个项目上&#xff0c;听到客户的global team有使用该事务代码&#xff0c;设置成了一个job…

Oracle RMAN备份相关信息查询

查询 RMAN 备份状态主要是通过视图V$RMAN_STATUS 来进行&#xff0c;这个视图可以查询到 RMAN 执行的操作。 我们主要查看两列&#xff1a;OPERATION 和 STATUS。 OPERATION 的值有&#xff1a;RMAN、BACKUP、DELETE、CROSSCHECK、DELETE OBSOLETE等。 STATUS的值有&#xff1a…

中国电信携手华为建成全球首个支持5G RedCap联合测试能力的5G开放实验室

近日&#xff0c;中国电信物联网开放实验室宣布与华为共同完成了5G RedCap实验室技术验证&#xff0c;并建成了全球首个具备5G R17标准RedCap联合测试能力的开放实验室。 此次技术验证&#xff0c;为RedCap的规模商用奠定了坚实基础&#xff0c;有助于打造RedCap行业终端生态认…

良心总结!Git 各指令的本质,真是通俗易懂啊

1前言 作为当前世界上最强大的代码管理工具Git相信大家都很熟悉&#xff0c;但据我所知有很大一批人停留在clone、commit、pull、push...的阶段&#xff0c;是不是对rebase心里没底只敢用merge&#xff1f;碰见版本回退就抓瞎&#xff1f;别问我怎么知道的&#xff0c;问就是&…

什么是成熟的自动化运维平台?

本文首发于知乎&#xff0c;由嘉为蓝鲸原创。 商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 当企业遇到运维管理对象的急速增长&#xff0c;业务需求频繁变更等传统运维场景问题时&#xff0c;依靠手工运维已经远远满足不了需求&#xff0c;因此我们需要搭建…

2022,itbird的年终总结报告

最近公司要求个人在做年终总结了&#xff0c;趁着这个机会&#xff0c;也想对自己的2022年进行一下回顾总结&#xff0c;最重要的是&#xff0c;对2023的目标&#xff0c;可以有一个指引。 就从工作和生活两方面来讲吧。 1.工作 1.1 行业的状态 本人从事的是android开发工作…

Cuda个别库函数的兼容性 - shuffle\数学库\原子

兼容性针对的是不同的Cuda版本和设备计算能力(compute capability) shuffle 在C\C扩展一节 新版本函数见Cuda12.0 文档 __shfl_sync, __shfl_up_sync, __shfl_down_sync, and __shfl_xor_sync exchange a variable between threads within a warp. Supported by devices of …

信创入围认证详解

信创是一个统称概念&#xff0c;实际是把现有与信息技术相关的行业结合在一起&#xff0c;命名为“信息技术应用创新产业”&#xff0c;简称“信创”。一般来说&#xff0c;信创包括基础硬件、基础软件、应用软件、信息安全四大板块。其中&#xff0c;基础硬件主要包括&#xf…

让最近爆火的ChatGPT来谈谈,作为一个技术人该如何写好一篇技术博文

ChatGPT 是由 OpenAI 训练的一个大型语言模型。专门设计用于回答用户提出的问题&#xff0c;我可以提供有价值的信息&#xff0c;并帮助用户解决问题 下面的回答均来自ChatGPT CharGPT如何写好一篇技术博文&#xff1f;写技术博文需要具备那些能力就用java实现冒泡排序来写一篇…

C语言画贝塞尔曲线的函数

程序截图 简单说明 这个函数就是 void drawBezierCurve(COLORREF color, const unsigned int len, ...) color 是贝塞尔曲线的颜色&#xff0c;len 是画出贝塞尔曲线所需要的点的个数&#xff0c;最少 1 个&#xff0c;不要乱传。之后的参数传的就是画出贝塞尔曲线要的点&am…

大数据时代,数据实时同步解决方案的思考—最全的数据同步总结

F、 客户端开发&#xff0c;在maven中引入canal的依赖 com.alibaba.otter canal.client 1.0.21 代码示例&#xff1a; package com.example; import com.alibaba.otter.canal.client.CanalConnector; import com.alibaba.otter.canal.client.CanalConnectors; import c…

[附源码]Nodejs计算机毕业设计基于Web美食网站设计Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

C++ Reference: Standard C++ Library reference: Containers: map: map: begin

C官网参考链接&#xff1a;https://cplusplus.com/reference/map/map/begin/ 公有成员函数 <map> std::map::begin C98 iterator begin(); const_iterator begin() const; C11 iterator begin() noexcept; const_iterator begin() const noexcept;返回指向开始的iterato…

[附源码]Python计算机毕业设计甘肃草地植物数字化标本库管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

图拉普拉斯矩阵

正定矩阵 在线性代数里&#xff0c;正定矩阵 (positive definite matrix) 有时会简称为正定阵。 广义定义&#xff1a;设M是n阶方阵&#xff0c;如果对任何非零向量z&#xff0c;都有z⃗TMz⃗>0\vec{z}^TM\vec{z}>0zTMz>0&#xff0c;则称M为正定矩阵。 狭义定义&…

CSS之display:grid的用法和动态:before content内容

CSS之display:grid的用法和动态:before content内容1. display:grid的用法2.动态:before content内容3.完整代码&#xff1a;项目诉求&#xff1a; 突然有个需求&#xff0c;就是 指定行列&#xff0c;并呈现N字型展示数据&#xff0c;如下所示&#xff1a; 有纠结是用display:…

[附源码]Python计算机毕业设计高校创新学分申报管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

来看!这才是久经沙场得 SQL 优化经验

跟着 SQL 优化得经验之谈&#xff0c;面试真的可以侃侃而谈。 那么面对复杂的关系数据&#xff0c;我们如何来优化&#xff0c;SQL如何玩转更优&#xff1f; 先抛出了4个关于优化方面的问题&#xff1a; 1.返回表中0.014%的数据应不应该走索引&#xff1f; 2.什么样的列必须…

股票买卖接口如何实现委托下单的功能?

股票买卖接口如何实现委托下单的功能&#xff1f;一般来说&#xff0c;股票买卖接口都是相关的人士已经设计好&#xff0c;并且是程序形式呈现出来的&#xff0c;和券商系统链接起来&#xff0c;这样就可以实现交易了&#xff0c;下面给分享关于股票买卖接口是如何执行委托下单…

计算机系统实验-DataLab

一.实验题目及要求 在给定规则限制下完成bits.c中的函数。其中最主要的规则如下&#xff1a; 整数规则 不能使用for while if等只能使用! ˜ & ˆ | << >>运算符只能使用int只能使用0-0xFF的常数使用运算符数不超过限制(Max ops)不能使用全局变量或调用函数…