将不确定有穷自动机转化为确定的有穷自动机
题目:将下列的NFA状态图转化为DFA 备注:构造NFA N的子集算法 算法步骤如下: 使用Java代码实现如上算法以及整个流程为:
package com.wcx;
import java.util.*;
public class NFAToDFA {
private static String startStateNode;
private static ArrayList<String> endStateNodes = new ArrayList<>();
private static boolean select = true;
public static void main(String[] args) {
NFAToDFA nfaToDFA = new NFAToDFA();
nfaToDFA.NFAToDFA();
}
private void NFAToDFA(){
selectStartAndEndStateInputWay();
ArrayList<String> NFA = getNFAStateDiagram();
HashMap<String, HashMap<String, String>> arrayToHashMapOfNFA = arrayToHashMapOfNFA(NFA);
if(select){
startStateNode = getStartStateNode(NFA);
if(startStateNode == null){
return;
}
endStateNodes = getEndStateNodes(NFA);
if(endStateNodes.size() == 0){
System.out.println("终态节点识别失败,请检查输入!");
return;
}
}
ArrayList<String> chars = getNFAInputChar(NFA);
HashMap<String, Object> nfaSonArray = getNFASonArray(arrayToHashMapOfNFA, startStateNode, chars);
ArrayList<ArrayList<String>> tArrays = (ArrayList<ArrayList<String>>)nfaSonArray.get("TArrays");
ArrayList<String> ttArray = (ArrayList<String>)nfaSonArray.get("TTArray");
String dfaStartNode = getDFAStartNode(startStateNode, tArrays);
ArrayList<String> dfaEndNodes = getDFAEndNodes(endStateNodes, tArrays);
printDFA(tArrays,dfaStartNode,dfaEndNodes,ttArray,chars);
}
private void printDFA(ArrayList<ArrayList<String>> tArrays,String dfaStartNode,ArrayList<String> dfaEndNodes,ArrayList<String> ttArray,ArrayList<String> chars){
ArrayList<String> DFA = new ArrayList<>();
System.out.println("NFA的状态K的子集: ");
for (int i = 0; i < tArrays.size(); i++) {
String node = "A" + i + " = " + tArrays.get(i);
DFA.add("[A" + i+"]");
System.out.println(node);
}
System.out.println("(1) DFA的状态集: S = " + DFA);
System.out.println("(2) DFA的字符表:∑ = " + chars);
System.out.println("(3) DFA的转换函数:");
for (int i = 0; i < ttArray.size(); i++) {
System.out.println(" "+ttArray.get(i));
}
System.out.println("(4) DFA的初态:S0 = "+DFA.get(Integer.parseInt(dfaStartNode)));
ArrayList<String> dfaEnd = new ArrayList<>();
for (int i = 0; i < dfaEndNodes.size(); i++) {
dfaEnd.add(DFA.get(Integer.parseInt(dfaEndNodes.get(i))));
}
System.out.println("(5) DFA的终态集合:S1 = " + dfaEnd);
}
private ArrayList<String> getDFAEndNodes(ArrayList<String> endStateNodes,ArrayList<ArrayList<String>> tArrays){
ArrayList<String> DFAEndStateNodes = new ArrayList<>();
for (String endStateNode : endStateNodes) {
int count = 0;
for (ArrayList<String> tArray : tArrays) {
if (tArray.indexOf(endStateNode) != -1) {
if (DFAEndStateNodes.indexOf(count+"") == -1) {
DFAEndStateNodes.add(count+"");
}
}
count++;
}
}
return DFAEndStateNodes;
}
private String getDFAStartNode(String startStateNode,ArrayList<ArrayList<String>> tArrays){
ArrayList<String> startStateNodes = new ArrayList<>();
int count = 0;
for (ArrayList<String> tArray : tArrays) {
if (tArray.indexOf(startStateNode) != -1) {
if(tArray.size() == 1){
return String.valueOf(count);
}
startStateNodes.add(count+"");
}
count++;
}
if(startStateNodes.size() != 1){
System.out.println("NFA子集筛选错误或者NFA初态筛选错误!");
return null;
}
return startStateNodes.get(0);
}
private HashMap<String,Object> getNFASonArray(HashMap<String, HashMap<String, String>> arrayToHashMapOfNFA,String startStateNode,ArrayList<String> chars){
ArrayList<String> array = new ArrayList<>();
array.add(startStateNode);
array = getEndState(startStateNode, arrayToHashMapOfNFA,array,"c");
ArrayList<ArrayList<String>> TArrays = new ArrayList<>();
ArrayList<String> TTArray = new ArrayList<>();
TArrays.add(array);
int count = 0;
do{
array = TArrays.get(count++);
for (String aChar : chars) {
ArrayList<String> a = move(array, aChar, arrayToHashMapOfNFA);
ArrayList<String> b = new ArrayList<>();
for (String s : a) {
b = getEndState(s, arrayToHashMapOfNFA, b, "c");
}
a.addAll(b);
int mark = 0;
for (ArrayList<String> tArray : TArrays) {
if (!equalToArray(tArray,a)) {
mark++;
}else{
TTArray.add("D([A"+(count-1) + "],"+aChar+") = [A" + mark + "]");
}
}
if(mark == TArrays.size()){
if(a.size() != 0){
TArrays.add(a);
}
TTArray.add("D([A"+(count-1) + "],"+aChar+") = [A" + mark + "]");
}
}
}while(count < TArrays.size());
HashMap<String,Object> hashMap = new HashMap<>();
hashMap.put("TArrays",orderByAes(TArrays));
hashMap.put("TTArray",TTArray);
return hashMap;
}
private ArrayList<String> getNFAInputChar(ArrayList<String> NFA){
ArrayList<String> chars = new ArrayList<>();
for (String s : NFA) {
String[] split = s.split(" ");
if((!"c".equals(split[2]))&&(chars.indexOf(split[2]) == -1)){
chars.add(split[2]);
}
}
return chars;
}
private String getStartStateNode(ArrayList<String> NFA){
ArrayList<String> startNodes = new ArrayList<>();
ArrayList<String> endNodes = new ArrayList<>();
for (String s : NFA) {
String[] s1 = s.split(" ");
startNodes.add(s1[0]);
endNodes.add(s1[1]);
}
for (String startNode : startNodes) {
if (endNodes.indexOf(startNode) == -1) {
return startNode;
}
}
System.out.println("NFA状态图输入有误,未找到初态节点!");
return null;
}
private ArrayList<String> getEndStateNodes(ArrayList<String> NFA){
ArrayList<String> startNodes = new ArrayList<>();
ArrayList<String> endNodes = new ArrayList<>();
ArrayList<String> endStateNodes = new ArrayList<>();
for (String s : NFA) {
String[] s1 = s.split(" ");
startNodes.add(s1[0]);
endNodes.add(s1[1]);
}
for (String endNode : endNodes) {
if (startNodes.indexOf(endNode) == -1) {
endStateNodes.add(endNode);
}
}
return endStateNodes;
}
private HashMap<String,HashMap<String,String>> arrayToHashMapOfNFA(ArrayList<String> NFA){
HashMap<String,HashMap<String,String>> hashMap = new HashMap<>();
for (String nfa : NFA) {
String[] strings = nfa.split(" ");
if (hashMap.get(strings[0]) != null) {
if(hashMap.get(strings[0]).get(strings[1])==null){
hashMap.get(strings[0]).put(strings[1],strings[2]);
}else{
hashMap.get(strings[0]).put(strings[1],hashMap.get(strings[0]).get(strings[1])+","+strings[2]);
}
}else{
HashMap<String,String> map = new HashMap<>();
map.put(strings[1],strings[2]);
hashMap.put(strings[0],map);
}
}
return hashMap;
}
private ArrayList<String> getNFAStateDiagram(){
ArrayList<String> NFA = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入NFA状态图关系:");
while (true){
String str = scanner.nextLine();
if(";".equals(str)){
break;
}
NFA.add(str);
}
return NFA;
}
public ArrayList<ArrayList<String>> orderByAes(ArrayList<ArrayList<String>> arrayLists){
for (ArrayList<String> arrayList : arrayLists) {
try{
ArrayList<Integer> array = new ArrayList<>();
for (String s : arrayList) {
array.add(Integer.parseInt(s));
}
Collections.sort(array);
for (int i = 0; i < arrayList.size(); i++) {
arrayList.set(i,array.get(i).toString());
}
}catch (Exception e){
return arrayLists;
}
}
return arrayLists;
}
public boolean equalToArray(ArrayList<String> array1,ArrayList<String> array2){
if(array1.size() != array2.size()){
return false;
}
for (String array : array1) {
boolean mark = false;
for (String s : array2) {
if (array.equals(s)) {
mark = true;
break;
}
}
if(!mark){
return false;
}
}
return true;
}
private ArrayList<String> move(ArrayList<String> array,String str,HashMap<String,HashMap<String,String>> map){
ArrayList<String> arrayList = new ArrayList<>();
for (String s : array) {
HashMap<String, String> hashMap = map.get(s);
if(hashMap == null){
continue;
}
Set<String> strings = hashMap.keySet();
for (String string : strings) {
String[] split = hashMap.get(string).split(",");
for (String s1 : split) {
if (s1.equals(str)) {
if(arrayList.indexOf(string) == -1){
arrayList.add(string);
}
}
}
}
}
return arrayList;
}
private ArrayList<String> getEndState(String node,HashMap<String,HashMap<String,String>> map,ArrayList<String> array,String str){
HashMap<String, String> hashMap = map.get(node);
if(hashMap == null){
return array;
}
Set<String> strings = hashMap.keySet();
for (String string : strings) {
if(hashMap.get(string).equals(str)){
array.add(string);
array = getEndState(string,map,array,str);
}
}
return array;
}
private void selectStartAndEndStateInputWay(){
Scanner scanner = new Scanner(System.in);
System.out.println("请选择初态和终态确认方式:");
System.out.println("======1、程序自动识别======");
System.out.println("======2、手动录入 ======");
String s = scanner.nextLine();
if("1".equals(s)){
return;
}else if("2".equals(s)){
System.out.print("请输入初态: ");
startStateNode = scanner.nextLine();
System.out.print("请输入终态集合,使用空格隔开:");
String endStates = scanner.nextLine();
endStateNodes.addAll(Arrays.asList(endStates.split(" ")));
select = false;
}else{
selectStartAndEndStateInputWay();
}
}
}
测试输入,以英文输入法的分号(;)表示本次录入结束(因为图的特殊性,输入的时候需要使用如下格式输入,起点(空格)终点(空格)字符) 例如NFA状态图中的第一个关系(0和1的表示方法)为0 1 c c表示图中ε特殊字符,因为在Java输入流中不方便表示,所以使用c来表示,当然也可以使用其他字符表示 运行结果 最终截图图 为便于书写,不妨将【A0】、【A1】、【A2】、【A3】、【A4】重新命名,用0、1、2、3、4分别表示,该DFA M 的状态转换图如图所示。
该方法仅供参考,不是最优结果,如果有需要,可以联系探讨
|