题目

将通过以下有穷自动机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. 编译原理——识别的字集为 包含奇数个1和奇数个0的二进制数串

    识别的字集为"包含奇数个1和奇数个0的二进制数串"

  2. 编译原理_正规集和正规式_有限自动机

    ** 正规集和正规式 ** 也就是说程序设计语言的合法单词是 正规集,而正规式可以用来表示正规集 正规集是集合 正规式的等价可以转换为集合的等价来证明 将每一类的单词符号写成一个正规式,通过或运算将这 ...

  3. [编译原理]词法分析实验之基于 DFA 的单词识别

    Spring-_-Bear 的 CSDN 博客导航 问题描述: 基于 DFA 的单词识别问题的一种描述是:编写一个程序,输入一个确定的有穷自动机(DFA),使用该 DFA 识别单词. 基本要求: 设置 ...

  4. 编译原理 | 由正规式构造确定的有穷自动机DFA

    词法分析: 由正规式构造确定的有穷自动机DFA 解题方法 1. 先由正规式构造转换系统 规则见下图: 2. 再由转换系统构造确定有穷自动机DFA (1) 求 Ia 假定 I 是转换图状态集 K 一个子 ...

  5. 【C++实现】编译原理 免考小队 NFA转换为等价的DFA

    背景 期末考试免考,冲! 实验名称 对任意给定的NFA M进行确定化操作 实验时间 2020年5月21日 到 2020年5月24日 院系 信息科学与工程学院 组员姓名 Chocolate.kry202 ...

  6. 编译原理——java 词法分析【有穷自动机实现】

    编译原理--实验1 实验要求 1) 基于词法规则设计词法分析器(20分) 画出确定的有穷自动机(确定化),并提供必要的文字说明.提交状态转换图.doc 2) 词法分析程序的编程实现(80分) (1) ...

  7. 编译原理——正规式转DFA算法概述

    一.概念概述 给定一个单词,判断该单词是否满足我们给定的单词描述规则,需要用到编译原理中词法分析的相关知识,其中涉及到的两个很重要的概念就是正规式(Regular Expression)和有穷自动机( ...

  8. 编译原理——DFA的编程实现

    前言:这是我学习编译原理,课程实验的内容,课程早已结束,现整理发表. 一.实验任务 编写一个C语言程序,模拟实现DFA识别字符串的过程. 二.实验内容 DFA的输入: DFA的存储与读写: DFA的正 ...

  9. 编译原理 LL1文法的判断和句子识别

    编译原理 LL1文法的判断和句子识别 LL1文法概述 点击查看百度百科 对文法G的句子进行确定的自顶向下语法分析的充分必要条件是,G的任意两个具有相同左部的 产生式A->α|β 满足下列条件: ...

最新文章

  1. 诊断IIS中的ASP0115错误
  2. Linux+mysql重置_linux环境mysql重置密码
  3. 邬贺铨:工业物联网的技术与前景
  4. Andorid应用去google广告
  5. One order search dynamic SQL build logic
  6. Ubuntu 12.04 修改/etc/resolv.conf重启后还原成修改前状态解决办法
  7. 自定义TBE算子入门,不妨从单算子开发开始
  8. 特斯拉正加快部署第三代Autopilot自动驾驶计算机
  9. linux rdma服务,在Linux中infiniband rdma差转转bw
  10. 读【重构】(3)——感悟重构——Decompose Conditional(分解条件式)
  11. 服务器搭建mutt邮件发送环境
  12. windows活动目录与网络系列(1)
  13. 沟通和编程一样,也是一门艺术系列4(沟通的原则)
  14. Word1——word 2016(笔记本预装)安装MathType 7教程
  15. 【智慧医疗】破解医疗数据孤岛,实现信息共享
  16. R语言:Newton法、似然函数
  17. 计计算机专用英语(常用1695个单词,带音标) 欢迎评论转发
  18. MAXIMO工作流待办邮件提醒配置
  19. vue3+element-plus动态设置字体大小
  20. 常见广域网协议及特点

热门文章

  1. 使用realsense d415进行拍照,延迟,to_string,string,开机自启
  2. Python量化交易+网格技术分析及实战测试
  3. 京东运维开发工程师一面经验总结2020
  4. 帆软认证BI工程师题库
  5. 我的2017年读书计划
  6. IDEA中代码无故报红解决方法
  7. iOS 指定压缩图片大小的解决方式
  8. 3D动作绑定_游戏建模大佬教你九招轻轻松松学会三维动画制作绑定技术
  9. 一个利用51单片机播放音乐的程序
  10. pagehelper原理 分页