有穷自动机【DFA】【编译原理】识别字符串的实现-编程
题目
将通过以下有穷自动机DFA的图,识别输入的字符串,并判断输入的字符串是否符合该DFA图。
图
分析
输入aab如何判断aab是否符合DFA图?
首先DFA图肯定是从起始位置(始态-双箭头指向的状态)-1位置开始执行,如果输入aab,首先从字符串头开始遍历,例如a符号在1位置转换为2,a(第二个a)又在2位置状态下4,b又在4状态下转换为2状态,然后字符串遍历结束。这个时候我们可以发现最终DFA的状态停在了2状态也就是终态(双圆圈的状态),所以DFA也停止,因次aab可以被DFA识别。
由上发现只要最终DFA的状态为终态,则该字符串遍能被该DFA识别,例如输入ab,不能识别最终状态为1不是终态。
特殊情况
输入的字符串中含有DFA中不存在的符号,例如输入acb,DFA中无对应的c符号,肯定不能识别。
思路
每个状态写一个子程序,相互调用
上代码
package BianYi;
/** DFA* 本方法只适应该DFA图* I Ia Ib * 1 2 3 0* 2 4 1 1* 3 1 5 0* 4 4 2 0* 5 2 3 1* */
import java.util.Scanner;public class Demo_02 {public static int count=0;//全局计数器 用于遍历输入的字符串public static boolean flag=false;//记录输入的字符串是否能被DFA识别,默认为false 全局变量public static void main(String[] args) { Scanner input=new Scanner(System.in);System.out.print("请输入一串字符串:");String str=input.next();//接收该字符串//先排除简单的情况 即输入的字符串中存在某个字符在DFA符号中无对应 例如输入aac c无对应(符号为a b)for(int i=0;i<str.length();i++) {//遍历输入的字符串 一一对比if(str.charAt(i)!='a'&&str.charAt(i)!='b') {//遍历的字符在DFA中无对应System.out.println("字符串:"+str+"不能被当前的DFA识别!");System.exit(0);//终止程序}}//遍历输入的字符串fun_01(str.charAt(count),str);if(flag) {System.out.print("字符串:"+str+"能被当前的DFA识别!");}else {System.out.println("字符串:"+str+"不能被当前的DFA识别!");}}public static boolean funCtion(String str,int t) {if((t==5||t==2)&&count==str.length()) {//如果此时count的值等于字符串的长度-即已经遍历到了最后一个字符了flag=true;//因为此处会调用fun_02或fun_05,而且fun_02或fun_05为终态,并且已经是遍历的最后一个字符 所以该字符串能被DFA识别return true;//让程序不再往下执行,不然会造成str.charAt(count)下标越界 }if((t==1||t==3||t==4)&&count==str.length()){flag=false;//因为此处会调用fun_03||04||01,而且都不为终态,并且已经是遍历的最后一个字符 所以该字符串不能被DFA识别return true;//让程序不再往下执行,不然会造成str.charAt(count)下标越界}return false; }public static void fun_01(char ch,String str) {//DFA中的1状态if(ch=='a') {count++;if(funCtion(str,2)) {return;}fun_02(str.charAt(count),str);}else {//ch=='b'count++;if(funCtion(str,3)) {return;}fun_03(str.charAt(count),str);}}public static void fun_02(char ch,String str) {//DFA中的2状态-终态if(ch=='a') {count++;if(funCtion(str,4)) {return;}fun_04(str.charAt(count),str);}else {//ch=='b'count++;if(funCtion(str,1)) {return;}fun_01(str.charAt(count),str);}}public static void fun_03(char ch,String str) {//DFA中的3状态if(ch=='a') {count++;if(funCtion(str,1)) {return;}fun_01(str.charAt(count),str);}else {//ch=='b'count++;if(funCtion(str,5)) {return;}fun_05(str.charAt(count),str);}}public static void fun_04(char ch,String str) {//DFA中的4状态if(ch=='a') {count++;if(funCtion(str,4)) {return;}fun_04(str.charAt(count),str);}else {//ch=='b'count++;if(funCtion(str,2)) {return;}fun_02(str.charAt(count),str);}}public static void fun_05(char ch,String str) {//DFA中的5状态-终态if(ch=='a') {count++;if(funCtion(str,2)) {return;}fun_02(str.charAt(count),str);}else {//ch=='b'count++;if(funCtion(str,3)) {return;}fun_03(str.charAt(count),str);}}
}
矩阵法-二维数组
开辟一个二维数组存在每个状态经过输入的符号转后后的状态
其中行为状态的个数,列为DFA中的符号个数+1,最后一列存储当前的状态是否为终态-01标记 1-为终态。
为了能使程序通用其他DFA图,将DFA状态之间的相关关系写入了文本中
文本存储规则:状态标识用阿拉伯数字表示,符号用字母表示
文本存储代码
package BianYi;
import java.io.BufferedReader;
import java.io.File;//导入包
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
//读取文本中的信息
public class FileText {public static int hang;//二维数组的行数public static int lie;//二维数组的列数private static int i=1;//目的是标记文本中的第一行,因为第一行只有2个数字,其他行有三个数字,且均以空格分离private static String path="C:\\Users\\wsg\\Desktop\\编译原理.txt";//定义文本的名称,private static File file;//定义一个File(File读取文件的流)的变量名static {//static 为静态代码块 程序运行只执行一次file = new File(path);if(!file.exists()){try {//捕获创建、读取文件时可能发生的异常file.createNewFile();//文件如果不存在会创建如果存在不会创建} catch (IOException e) {e.printStackTrace();}}}public static int[][] fun(int[][] array) {try {array=readDataFromFile4(file,array); } catch (IOException e) {e.printStackTrace();}//返回权限return array;}private static int[][] readDataFromFile4(File file,int[][] array) throws IOException {//声明为staic可用类名访问 throws表示该方法可能抛出IOException异常BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));//缓冲流-读取String str = "";//局部变量需要先赋值后引用int count=0;//数组行数的统计while((str = reader.readLine())!=null){//如果没有读取到最后一行String[] stuInfo= str.split("\\s+");//按照空格正则分割,全部读取if(i==3) {Demo_01.chArry=stuInfo;}if(i==1) {//第一行存取的是行数和列数hang=Integer.valueOf(stuInfo[1]).intValue();//将读取的行数转换为整数类型lie=Integer.valueOf(stuInfo[3]).intValue(); //堆区开辟数组空间array=new int[FileText.hang][FileText.lie+1];//声明一个二维数组,行数和列数从文本中读取 其中行为状态的个数,列为输入的符号个数和初始态0 1 }if(i>3){//当读取的行数大于三时,此时读取的便是状态之间的转换关系,将其存储在二维数组中 array[count][0]=Integer.valueOf(stuInfo[0]).intValue();//存储某个状态经过输入某个字符转换后的状态array[count][1]=Integer.valueOf(stuInfo[1]).intValue();//存储某个状态经过输入另一个字符转后的状态array[count][2]=Integer.valueOf(stuInfo[2]).intValue();//存储此时状态是否为初始态 0 1count++;}i++;}return array;//将新开辟的数组空间返回 便于调用 不返回会造成访问数组为null-即只能在该方法中访问该数组}
}
矩阵代码
package BianYi;import java.util.Scanner;
/** 文本中的存储规则:* 如果DFA的输入字符在图中为数字 则用字母a b c...代替* 如果DFA的状态在图中为字母,则用数字 1 2 3....代替* */
//有穷自动机DFA程序
public class Demo_01 {public static String[] chArry;//将有DFA的输入符号存储在chArry中 例如 a bpublic static void main(String[] args) { Scanner input=new Scanner(System.in);//输入语句int[][] array = null;//首先定义一个二维数组,赋值为空 ,在读取的文件类FileText中赋值array=FileText.fun(array);//传递数组名称,分配空间,并且读取文本中的内容(各状态转换之间的关系) System.out.print("I ");for(String st:chArry) {//将DFA中的输入字符打印出来 例如 a bSystem.out.print("I"+st+" ");//空格分割}System.out.println();//换行for(int i=0;i<FileText.hang;i++) {//将二维表中的状态关系全部打印出来 最后一列存储的是该状态是否终态0-1System.out.print((i+1)+" ");for(int j=0;j<FileText.lie+1;j++) {System.out.print(array[i][j]+" ");//以空格隔开}System.out.println();//换行}System.out.print("请输入一串字符串:");String str=input.next();//输入用户需要识别的字符串 if(funCtion(str,array)) {//调用funCtion函数,传递用户输入的字符串以及存储各状态转换关系的二维数组,识别成功返回tureSystem.out.print("字符串:"+str+"可以被该有穷自动机识别");}else {System.out.print("字符串:"+str+"不可以被该有穷自动机识别");}}public static boolean funCtion(String str,int[][] array) {//如果识别成功 返回true 否则返回falsechar[] strArray=str.toCharArray();//将要用户输入的字符串转换为char[]类型,便于一个一个比较与转换boolean flag=false;//记录用户输入的字符串与DFA中的字符号是否一模一样,默认不一样//第一种情况 输入的字符在DFA中找不到该字符 例如 DFA中的符号是a b 用户输入的是abc c不存在String s;//char[]类型和String[]类型无法比较,需要转换,s存储strArray[i]for(int i=0;i<strArray.length;i++) {//遍历用户输入的字符串flag=false;//用户输入的字符串中每一个字符都默认为在DFA符号中无对应s=String.valueOf(strArray[i]);//将字符char类型转换为string类型便于比较for(int j=0;j<chArry.length;j++) {//遍历DFA中的字符号if(s.equals(chArry[j])) {//如果用户输入的字符串中的每一个字符在DFA中有相应的字符号对应,改变flag的状态flag=true;//如果用户输入的字符串的每个字符在DFA中都有符号对应,则flag一直为truebreak;//只要当前的该单个字符在DFA中有对应的字符号就不需要再遍历当前查找了,退出内层循环}} if(!flag) {//表明用户输入的字符串的字符存在与DFA中的字符号不一致;则该字符串肯定不能被该机器识别 则不需要再查找,直接返回falsereturn false;}}int num=1;//如果输入的是aab a在某一列 则num存储某一列的DFA转换状态for(int i=0;i<strArray.length;i++) {//遍历用户输入的字符串int n=-1;//记录当前遍历的字符在二维表中对应的列数(根据DFA中的符号判断)s=String.valueOf(strArray[i]);//将字符char类型转换为string类型便于比较for(int j=0;j<chArry.length;j++) {//遍历DFA中的符号if(s.equals(chArry[j])) {//如果当前遍历的字符与当前遍历的DFA中的符号相等n=j;//将s在二维表中的列数赋予nnum=array[num-1][j];//将要这列中的break;}}if(i==strArray.length-1&&array[num-1][2]==1) {//已经扫描完最后一个字符,并且当前该字符所在的状态为1 则说名该字符符合该有穷自动机return true;}//System.out.println(n);}return false;}
}
结果
注:此程序对于一些DFA图可能识别不了,例如某个状态转换为其他状态只有一种输入符号,那么DFA中的其他符号在二维数组中的存储值应该为空(可置为0,增加判断即可)。
如下图,如果输入abca字符串则结果为识别不成功,因为第输入a转换为2状态后,2状态没有与b字符有关的操作。
有穷自动机【DFA】【编译原理】识别字符串的实现-编程相关推荐
- 编译原理——识别的字集为 包含奇数个1和奇数个0的二进制数串
识别的字集为"包含奇数个1和奇数个0的二进制数串"
- 编译原理_正规集和正规式_有限自动机
** 正规集和正规式 ** 也就是说程序设计语言的合法单词是 正规集,而正规式可以用来表示正规集 正规集是集合 正规式的等价可以转换为集合的等价来证明 将每一类的单词符号写成一个正规式,通过或运算将这 ...
- [编译原理]词法分析实验之基于 DFA 的单词识别
Spring-_-Bear 的 CSDN 博客导航 问题描述: 基于 DFA 的单词识别问题的一种描述是:编写一个程序,输入一个确定的有穷自动机(DFA),使用该 DFA 识别单词. 基本要求: 设置 ...
- 编译原理 | 由正规式构造确定的有穷自动机DFA
词法分析: 由正规式构造确定的有穷自动机DFA 解题方法 1. 先由正规式构造转换系统 规则见下图: 2. 再由转换系统构造确定有穷自动机DFA (1) 求 Ia 假定 I 是转换图状态集 K 一个子 ...
- 【C++实现】编译原理 免考小队 NFA转换为等价的DFA
背景 期末考试免考,冲! 实验名称 对任意给定的NFA M进行确定化操作 实验时间 2020年5月21日 到 2020年5月24日 院系 信息科学与工程学院 组员姓名 Chocolate.kry202 ...
- 编译原理——java 词法分析【有穷自动机实现】
编译原理--实验1 实验要求 1) 基于词法规则设计词法分析器(20分) 画出确定的有穷自动机(确定化),并提供必要的文字说明.提交状态转换图.doc 2) 词法分析程序的编程实现(80分) (1) ...
- 编译原理——正规式转DFA算法概述
一.概念概述 给定一个单词,判断该单词是否满足我们给定的单词描述规则,需要用到编译原理中词法分析的相关知识,其中涉及到的两个很重要的概念就是正规式(Regular Expression)和有穷自动机( ...
- 编译原理——DFA的编程实现
前言:这是我学习编译原理,课程实验的内容,课程早已结束,现整理发表. 一.实验任务 编写一个C语言程序,模拟实现DFA识别字符串的过程. 二.实验内容 DFA的输入: DFA的存储与读写: DFA的正 ...
- 编译原理 LL1文法的判断和句子识别
编译原理 LL1文法的判断和句子识别 LL1文法概述 点击查看百度百科 对文法G的句子进行确定的自顶向下语法分析的充分必要条件是,G的任意两个具有相同左部的 产生式A->α|β 满足下列条件: ...
最新文章
- 诊断IIS中的ASP0115错误
- Linux+mysql重置_linux环境mysql重置密码
- 邬贺铨:工业物联网的技术与前景
- Andorid应用去google广告
- One order search dynamic SQL build logic
- Ubuntu 12.04 修改/etc/resolv.conf重启后还原成修改前状态解决办法
- 自定义TBE算子入门,不妨从单算子开发开始
- 特斯拉正加快部署第三代Autopilot自动驾驶计算机
- linux rdma服务,在Linux中infiniband rdma差转转bw
- 读【重构】(3)——感悟重构——Decompose Conditional(分解条件式)
- 服务器搭建mutt邮件发送环境
- windows活动目录与网络系列(1)
- 沟通和编程一样,也是一门艺术系列4(沟通的原则)
- Word1——word 2016(笔记本预装)安装MathType 7教程
- 【智慧医疗】破解医疗数据孤岛,实现信息共享
- R语言:Newton法、似然函数
- 计计算机专用英语(常用1695个单词,带音标) 欢迎评论转发
- MAXIMO工作流待办邮件提醒配置
- vue3+element-plus动态设置字体大小
- 常见广域网协议及特点