实验1-正则表达式与有限自动机1
本实验是关于正则表达式和有限自动机的实验,旨在通过编程实现正则表达式转换为 NFA,深入理解正则表达式、NFA、DFA 及其识别的语言。
实验目的
* 通过本次实验,加深对正则表达式、NFA、DFA 及其识别的语言的理解。
实验内容
1. DFA 的输入与 DFA 的存储:确定 DFA 的数据结构以及存储格式。
2. DFA 的正确性检查:DFA 的五元组是否正确。
3. 输入任意一个整数 N,DFA 的能列表显示其识别的所有长度小于等于 N 的字符串。
4. DFA 的规则字符串判定:输入(或用字符集随机生成)一个字符串,模拟 DFA 认识字符串的过程判定该字符串是否是规则字符串(属于 DFA 的语言集)。
算法思想及问题对策
1. 算法描述:采用数组存放 DFA 的状态转换图,由于这里的数组是用的普通数组,不能存放字符(或者要转换为 ASCILL 码),因此采用将所有字符存放在一个数组 e 中,字符在 e 中的位置就代表着这个字符。
2. 对于 DFA 五元组的校验做了简单的判断,首先就是始态和终态不能比输入的最大状态还大其次就是每个元素都要在字母表中,在就是如果 DFA 表的一个项目已经被填写输入了,这时再次要在这个项目中输入,如果输入的不是和已经存在的值相同,则这个 DFA 必然出错。
3. 对于识别长度小于 n 的可识别串的输出,这里采用递归搜索的形式进行,从始态开始搜索,按照元素在字母表中的位置进行,没搜索到一个就输出一个,当搜索到当前的长度大于输入的 n 的值的时候,其后面的必然都是长度大于 n 的字符串,此时返回,然后进行上一层的下一个元素的搜索。总结起来就是一个 DFS。
4. 对于字符串的识别,从始态开始,用一个指针记录识别到字符串的那个位置的字符,当当前状态和当前字符在 DFA 存储数组中有值时,状态转移到改值记录的状态,指针后移一位,如果中途发 DFA 数组中不存在值,则报错。若指针移到了字符串的末尾,此时若状态为终态则识别成功,否则识别失败。
设计过程中的问题与对策
1. 对于长度小于 n 的能识别字符串的递归搜索一直有问题,后来发现是玲姐条件的设置有问题,当长度到达了 n-1 就不需要再次的递归了。
2. 对于字母表的存储,一开始是想用 map,但是后来发现 map 不好去遍历,所以改成了一般的数组。
3. 字符串识别的时候没有考虑字符串最后的状态是不是终态,而导致只要每一个元素都有下一状态就会识别成功,后来加入了一个函数判断最后一个状态是否为终态。
具体实现
1. 数据结构以及变量的说明:
* int sum_end = 0; 表示终态的个数
* int status = 0; 表示 DFA 中终态数的个数
* int elem = 0; 代表元素的个数,即字母表中的元素个数
* int start = 0; DFA 的开始状态
* int num = 0; 用于完成识别长度小于 n 的字符串的 n 的输入保存
* int dfa[100][100]; 存储 DFA 的矩阵
* int enddfa[100]; 终态集合
* char e[20]; 字母表的元素
* vector<int> vec; 识别长度小于 n 的可识别字符串时,方便存储输出。
2. 辅助函数:
* int getelemlocal(char *a,char b) 该函数输入字符串和字符,查找该字符是否在字符串中存在,存在则返回该字符在字符串中的位置,否则返回-1。用来获取字母表中的元素的映射位置。
* int inend(int* a,int b,int len) 输入字符串 a(终态集合)和长度 len,输入 b 状态,用来判段该状态 b 是否是属于终态集,是则返回 1,不是则返回 0。用于 DFA 的识别。
* void search(int now_status,int n,int now_elem_num) 该函数用于递归搜索长度小于 n 的可识别字符串,并且打印出来。Now_status 是当前所在的状态,n 是当前字符串的长度,now_elem_num 是要输入的字母表元素(这里用他在字母表数组中的下标来表示)。