编译原理:正规式转变成DFA算法

//将正规式转变成NFA
package hjzgg.formal_ceremony_to_dfa;import java.util.ArrayList;
class Edge{public int u, v;public char key;public Edge(int u, int v, char key) {super();this.u = u;this.v = v;this.key = key;}@Overridepublic String toString() {return u + "->" + v + " " + key;}@Overridepublic boolean equals(Object arg0) {Edge tmp = (Edge)arg0;return tmp.u==this.u && tmp.v==this.v && tmp.key==this.key;}@Overridepublic int hashCode() {return u+v+key;} }class NFA{public static final int MAX_NODE = 100;private boolean finalState[] = new boolean[MAX_NODE];//记录每一个节点是否为终态private String formal_ceremony;//正规式字符串private int cnt_node=1;//记录节点的个数private Map<Integer, Integer> endNode = new TreeMap<Integer, Integer>();//每一个开始节点对应的终端节点private ArrayList<Edge> nodeAl = new ArrayList<Edge>();private Vector<Pair>[] g = new Vector[MAX_NODE];//NFA图private Set<Character> st = new TreeSet<Character>();//正规式中出现的字符的集合public NFA(String formal_ceremony) {super();this.formal_ceremony = formal_ceremony;}private void addEdge(int u, int v, char ch){nodeAl.add(new Edge(u, v, ch));if(g[u] == null) g[u] = new Vector<Pair>();g[u].add(new Pair(v, ch));if(ch!='$')st.add(ch);}public boolean kernel_way(int fa, int ld, int rd, boolean isClosure){//fa表示区间的开始点,正规式的区间[ld, rd], isClosure表示这段区间查是否存在闭包 if(ld < 0 || rd >= formal_ceremony.length()){System.out.println("正规式不正确---发生数组越界!");return false;}int pre_node = fa;int inBracket = 0;//判断'|'是否在括弧内for(int i=ld; i<=rd; ++i){if(formal_ceremony.charAt(i)=='(') ++inBracket;else if(formal_ceremony.charAt(i)==')') --inBracket;else if(formal_ceremony.charAt(i)=='|' && 0==inBracket){if(!kernel_way(fa, ld, i-1, isClosure)) return false;if(!kernel_way(fa, i+1, rd, isClosure)) return false;return true;}}for(int i=ld; i<=rd; ++i){if(formal_ceremony.charAt(i)=='('){//又是一个子区间//寻找和 该 '('相匹配的')'int cntLeftBracket = 0;//统计遍历过程中'('出现的次数,遇到')'减去1int posRightBracket = -1;//记录相匹配的')'的位置int posLeftBracket = i;for(int j=i+1; j<=rd; ++j){if(formal_ceremony.charAt(j)=='(')++cntLeftBracket;else if(formal_ceremony.charAt(j)==')'){if(cntLeftBracket == 0){posRightBracket = j;break;}--cntLeftBracket;}}if(posRightBracket == -1){//出错System.out.println("正规式出错----括弧不匹配!");return false;}int nodeFather = 0;//括弧内正则式的开始节点if(posRightBracket+1 <= rd && formal_ceremony.charAt(posRightBracket+1)=='*'){i = posRightBracket+1;//过滤掉"()*"addEdge(pre_node, ++cnt_node, '$');//表示这一条边为空pre_node = cnt_node;nodeFather = cnt_node;addEdge(pre_node, ++cnt_node, '$');//表示这一条边为空pre_node = cnt_node;//处理()*括弧内的正规式if(!kernel_way(nodeFather, posLeftBracket+1, posRightBracket-1, true)) return false;} else {nodeFather = pre_node;if(!kernel_way(nodeFather, posLeftBracket+1, posRightBracket-1, false))//对于"(101)", 看成101return false;i = posRightBracket;}} else {//单个字符if(formal_ceremony.charAt(i)==')') continue;if(i+1 <= rd && formal_ceremony.charAt(i+1)=='*'){addEdge(pre_node, ++cnt_node, '$');//表示这一条边为空pre_node = cnt_node;addEdge(pre_node, pre_node, formal_ceremony.charAt(i));if(i+1==rd && isClosure)addEdge(pre_node, fa, '$');//表示这一条边为空并且是连接到父亲节点else{if(endNode.containsKey(fa))addEdge(pre_node, endNode.get(fa), '$');else{addEdge(pre_node, ++cnt_node, '$');//表示这一条边为空if(i==rd) endNode.put(fa, cnt_node);//记录非闭包状态下 第一个节点对应的最后一个节点 }}pre_node = cnt_node;++i;//过滤*} else {if(i==rd && isClosure){//是闭包的情况 addEdge(pre_node, fa, formal_ceremony.charAt(i));} else{if(endNode.containsKey(fa))addEdge(pre_node, endNode.get(fa), formal_ceremony.charAt(i));else{addEdge(pre_node, ++cnt_node, formal_ceremony.charAt(i));if(i==rd) endNode.put(fa, cnt_node);//记录非闭包状态下 第一个节点对应的最后一个节点 }}pre_node = cnt_node;}}}return true;}private void checkFinalState(){//检查哪一个节点是终态for(int i=1; i<=cnt_node; ++i){int cc = 0;if(g[i] == null){//表明是终态finalState[i] = true;continue;}for(int j=0; j<g[i].size(); ++j)if(g[i].elementAt(j).v != i)++cc;if(cc == 0)//表明是终态finalState[i] = true;}}public boolean[] getFinalState(){return finalState;}public Vector<Pair>[] getNFAGraphics(){if(kernel_way(1, 0, formal_ceremony.length()-1, false)){ // for(Edge e : nodeAl)//打印NFA // System.out.println(e); checkFinalState();return g;}return null;}public Set<Character> getCharacterSet(){return st;}public void outputNFA(){if(kernel_way(1, 0, formal_ceremony.length()-1, false)){checkFinalState();for(Edge e : nodeAl)System.out.println(e);}} }/** 将正规式转换成NFA* */ public class ToNFA {public static void main(String[] args){String formal_ceremony = "0*(100*)*0*"; // String formal_ceremony = "1(1010*|1(010)*1)*0"; // String formal_ceremony = "1(0|1)*101"; // String formal_ceremony = "0*1*(010)0*1*"; // String formal_ceremony = "(0|1|2)*"; // String formal_ceremony = "0|1"; // String formal_ceremony = "0|1|2|3"; // String formal_ceremony = "(0|1|6)|(2|3)|(4|5)"; // String formal_ceremony = "(0|1)*|(2|3)*"; // String formal_ceremony = "((10)|(01)*|(0|1))";NFA nfa = new NFA(formal_ceremony);nfa.outputNFA();} }
//将NFA转变成确定化DFA
package hjzgg.formal_ceremony_to_dfa;import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; import java.util.Set; import java.util.Vector;
class Pair {public int v;public char ch;public Pair(int v, char ch) {super();this.v = v;this.ch = ch;}}class MyHashSet extends HashSet<Integer>{//重写 set 集合的 hashcode()和equals()方法private int state;public void setState(int state){this.state = state;}public int getState(){return state;}@Overridepublic boolean equals(Object arg0) {MyHashSet tmp = (MyHashSet)arg0;if(tmp.size() != this.size()) return false;Iterator<Integer> it = this.iterator();while(it.hasNext()){if(!tmp.contains(it.next())) return false;}return true;}@Overridepublic int hashCode() {int sum = 0;Iterator<Integer> it = this.iterator();while(it.hasNext())sum += (((java.lang.Integer)it.next()).intValue());return sum;} }class DefinedNFA{private int dfaNode = 0;//defined DFA节点的个数private boolean[] finalState = null;//表示NFA中哪一个节点是终态private boolean[] newFinalState = new boolean[NFA.MAX_NODE] ;private Vector<Pair>[] g = null;//NFA 图private Set<Edge>edgeSet = new HashSet<Edge>(); //标记图中的边是否被访问过private MyHashSet st = null; //集合,表示每一个子集状态private Queue<MyHashSet> queue = new LinkedList<MyHashSet>();//存放要执行的子集状态private Set<MyHashSet> sst = new HashSet<MyHashSet>();private Set<Character> characterSet = null;//正规式中的字符的集合private ArrayList<Edge> nodeAl = new ArrayList<Edge>();//NFA边的集合public DefinedNFA(Vector<Pair>[] g, Set<Character> characterSet, boolean[] finalState) {super();this.g = g;this.characterSet = characterSet;this.finalState = finalState;}public Set<Character> getCharacterSet(){return characterSet;}public int getDfaNode(){return dfaNode;}public boolean[] getNewFinalState(){return newFinalState;}public ArrayList<Edge> getNodeAl(){return nodeAl;}private void dfs(int u, char ch){if(g[u]==null) return ;int len = g[u].size();for(int i=0; i<len; ++i){Pair pair = g[u].elementAt(i);Edge edge = new Edge(u, pair.v, pair.ch);if(!edgeSet.contains(edge) && pair.ch==ch){edgeSet.add(edge);st.add(pair.v);dfs(pair.v, '$');}}}public void checkIsFinalState(Set<Integer> st, int state){Iterator<Integer> it = st.iterator();while(it.hasNext()){int val = it.next();if(finalState[val])newFinalState[state] = true;}}private void initFirstSet(){edgeSet.clear();st = new MyHashSet();st.add(1);st.setState(++dfaNode);dfs(1, '$');checkIsFinalState(st, dfaNode);sst.add(st);queue.add(st);}private void addEdge(int u, int v, char ch){nodeAl.add(new Edge(u, v, ch));}public void ToStateMatrix(){initFirstSet();while(!queue.isEmpty()){MyHashSet myset = queue.poll();for(Character ch : characterSet){st = new MyHashSet();for(Integer i : myset){edgeSet.clear();dfs(i, ch);}if(st.size()>0){if(!sst.contains(st)){sst.add(st);queue.add(st);st.setState(++dfaNode);checkIsFinalState(st, dfaNode);} else {Iterator<MyHashSet> it = sst.iterator();while(it.hasNext()){MyHashSet tmp = it.next();if(tmp.equals(st)){st = tmp;break;}}}addEdge(myset.getState(), st.getState(), ch);} }}}public void outputDFA(){ToStateMatrix();//有状态转换矩阵得到defined NFAfor(Edge e : nodeAl)System.out.println(e);}}public class ToDefinedDFA {public static void main(String[] args) { // String formal_ceremony = "((10)|(01)*|(0|1))"; // String formal_ceremony = "(0|1|6)|(2|3)|(4|5)"; // String formal_ceremony = "1(0|1)*101";String formal_ceremony = "0*(100*)*0*";NFA nfa = new NFA(formal_ceremony);DefinedNFA definedDFA = new DefinedNFA(nfa.getNFAGraphics(), nfa.getCharacterSet(), nfa.getFinalState());definedDFA.outputDFA();}}
//将确定化DFA最小化
package hjzgg.formal_ceremony_to_dfa;import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set;
class MinimumDFA{private boolean[] newFinalState = null;//由确定化DFA得到private ArrayList<Edge> nodeAl = null;//由确定化DFA得到private int dfaNode;//确定化DFA节点的个数private Set<Character> characterSet = null;//正规式中的字符的集合private ArrayList<Set<Integer>> setList = new ArrayList<Set<Integer>>(); public MinimumDFA(boolean[] newFinalState, ArrayList<Edge> nodeAl, int dfaNode, Set<Character> characterSet) {super();this.newFinalState = newFinalState;this.nodeAl = nodeAl;this.dfaNode = dfaNode;this.characterSet = characterSet;}private void init(){//利用分割法将集合分成终态和非终态Set<Integer> finalStateSet = new HashSet<Integer>();Set<Integer> NofinalStateSet = new HashSet<Integer>();for(int i=1; i<=dfaNode; ++i)if(newFinalState[i])//终态 finalStateSet.add(i);else NofinalStateSet.add(i);setList.add(finalStateSet);setList.add(NofinalStateSet);}public void toMinimumDfa(){init();boolean flag = true;ArrayList<Set<Integer>> tmpSetList = new ArrayList<Set<Integer>>();while(flag){flag = false;hjzgg:for(int k=0; k<setList.size(); ++k){Set<Integer> st = setList.get(k);if(st.size()<=1) continue;for(Character ch : characterSet){Map<Integer, Integer> mp = new HashMap<Integer, Integer>();for(int i=0; i<nodeAl.size(); ++i){//st集合(也就是map的val值)在 ch这个点对应的集合 {st}a = {...}Edge edge = nodeAl.get(i);if(edge.key == ch && st.contains(edge.u))mp.put(edge.u, edge.v);}

            for(Integer i : st)
              if(!mp.containsKey(i))//表明i节点对应的是一条空边
                mp.put(i, -1);

//将st集合拆分成两个不想交的集合Set<Integer> firstSet = new HashSet<Integer>();Set<Integer> secondSet = new HashSet<Integer>();for(int j=0; j<setList.size(); ++j){firstSet.clear();secondSet.clear();Set<Integer> tmpSt = setList.get(k);for(Entry<Integer, Integer> entry : mp.entrySet()){//返回此映射中包含的映射关系的 set 视图。返回的 set 中的每个元素都是一个 Map.Entryif(tmpSt.contains(entry.getValue()))firstSet.add(entry.getKey());else secondSet.add(entry.getKey());}if(firstSet.size()!=0 && secondSet.size()!=0){flag = true;//如果发现可以拆分的集合,则继续最顶层的while循环for(Integer i : tmpSt){//将firstSet 和 secondSet中都没有的元素添加到firstSet中if(!firstSet.contains(i) && !secondSet.contains(i))firstSet.add(i);}setList.remove(k);setList.add(firstSet);setList.add(secondSet);break hjzgg;}}}}}
//        for(int k=0; k<setList.size(); ++k)//输出最终的集合划分
//            System.out.println(setList.get(k));
//        System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");for(int k=0; k<setList.size(); ++k){Set<Integer> st = setList.get(k);if(st.size() > 1){//看成是一个等价的状态,选择第一个元素当作代表int first=0;for(Integer i : st){//取得第一个元素first = i;break;}ArrayList<Edge> tmpList = new ArrayList<Edge>();for(int i=0; i<nodeAl.size(); ++i){//遍历所有的边,找到不是firstEdge edge = nodeAl.get(i);if(st.contains(edge.u) && edge.u!=first){nodeAl.remove(i);--i;} else if(st.contains(edge.v) && edge.v!=first){nodeAl.remove(i);--i;tmpList.add(new Edge(edge.u, first, edge.key));}}nodeAl.addAll(tmpList);}}}public void outputMinimumDFA(){
//        for(int i=0; i<nodeAl.size(); ++i)//输出未确定化的DFA
//            System.out.println(nodeAl.get(i));
        toMinimumDfa();for(int i=0; i<nodeAl.size(); ++i)System.out.println(nodeAl.get(i));}
}public class ToMinimumDFA {public static void main(String[] args) {
//        String formal_ceremony = "1(0|1)*101";String formal_ceremony = "0*(100*)*0*";NFA nfa = new NFA(formal_ceremony);DefinedNFA definedDFA = new DefinedNFA(nfa.getNFAGraphics(), nfa.getCharacterSet(), nfa.getFinalState());definedDFA.ToStateMatrix();MinimumDFA minimumDFA = new MinimumDFA(definedDFA.getNewFinalState(), definedDFA.getNodeAl(), definedDFA.getDfaNode(), definedDFA.getCharacterSet());minimumDFA.outputMinimumDFA();}}

 

转载于:https://www.cnblogs.com/hujunzheng/p/4421132.html

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

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

相关文章

C语言实现音乐播放器(Linux madplay)

&#xff08;一&#xff09;需求分析 1.扫描指定路径下的音乐&#xff0c;并显示出来 2.实现音乐的播放、暂停、上一首和下一首的功能 3.程序退出释放内存资源 &#xff08;二&#xff09;思路 1.扫描出指定路径下的音乐文件(便利指定文件夹&#xff0c;找出音频文件放在数组…

编译原理(简单自动词法分析器LEX)

编译原理&#xff08;简单自动词法分析器LEX&#xff09;源程序下载地址&#xff1a; http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7%90%86%E7%AE%80%E5%8D%95LEX%EF%BC%88%E8%AF%8D%E6%B3%95%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90%E5%99%A8%EF%…

虚拟机中安装linux

&#xff08;一&#xff09;前言 就在昨天电脑的固态突然崩掉&#xff0c;无奈重新把系统装在的以前的硬盘上&#xff0c;为了能够继续工作重新配置嵌入式linux系统开发环境&#xff0c;本教程主要记录在虚拟机中安装linux。 &#xff08;二&#xff09;环境准备 虚拟机&…

编译原理简单语法分析器(first,follow,分析表)源码下载

编译原理&#xff08;简单语法分析器下载&#xff09; http://files.cnblogs.com/files/hujunzheng/%E5%8A%A0%E5%85%A5%E5%90%8C%E6%AD%A5%E7%AC%A6%E5%8F%B7%E5%90%8E%E7%9A%84%E8%AF%AD%E6%B3%95%E5%88%86%E6%9E%90%E5%99%A8.zip 转载于:https://www.cnblogs.com/hujunzheng…

Ubuntu设置root登录

1.、Ubuntu 管理员用户 root 默认没有密码&#xff0c;在使用前最好添加密码&#xff0c;使用指令&#xff1a; sudo passwd root 注意&#xff1a;命令行输入密码时不显示&#xff0c;输入时需注意密码的准确性&#xff1b; 2、Ubuntu 想要用 root 帐户登录&#xff0c;可在普…

vim配置之spacevim

为了更好的利用vim&#xff0c;我们一般需要自己配置&#xff0c;今天介绍了一下经常用的spacevim &#xff08;一&#xff09;配置环境 Ubuntu16.04vim 7.4版本以上(必须&#xff01;&#xff01;) &#xff08;二&#xff09;安装spacevim 1.检查vim的版本&#xff1a; v…

Ubuntu更换gnome桌面环境后不能root登录

安装完Ubuntu后感觉界面有点丑陋&#xff0c;安装了gnome桌面环境试一下 sudo apt-get install gnome-shell sudo apt-get install ubuntu-gnome-desktop如果选择了lightdm后可以使用sudo dpkg-reconfigure gdm3 重新改回gdm3 sudo apt-get install unity-tweak-tool sudo ap…

Ubuntu下安装tilix终端仿真器

安装环境 Ubuntu 16.04 操作步骤 首先添加这个终端模拟器仓库的公钥。这里我都是以root超级用户权限操作的&#xff0c;如果没有的话&#xff0c;请在命令前面加sudo。 add-apt-repository ppa:webupd8team/terminixapt update安装Tilix。 apt install tilix安装完成测试结…

(扩展欧几里德算法)zzuoj 10402: C.机器人

10402: C.机器人 Description Dr. Kong 设计的机器人卡尔非常活泼&#xff0c;既能原地蹦&#xff0c;又能跳远。由于受软硬件设计所限&#xff0c;机器人卡尔只能定点跳远。若机器人站在&#xff08;X&#xff0c;Y&#xff09;位置&#xff0c;它可以原地蹦&#xff0c;但只可…

vim配置之snippets代码块

&#xff08;一&#xff09;目的 我们在编写程序的过程中&#xff0c;经常会敲一些重复的代码&#xff0c;我们可以利用snippets来达到输入简写来敲出完整的代码 &#xff08;二&#xff09;安装步骤 安装使用Vundle,没有vbundle的先执行下面的命令 git clone https://gith…

Ubuntu 16.04 安装CodeBlocks

博主作为嵌入式开发者&#xff0c;经常使用c/c开发&#xff0c;所以今天来装一下经常使用的codeblocks&#xff0c;linux下代码编辑器有好多&#xff0c;可以上网搜一下linux下常用的代码编辑器就会出来好多&#xff0c;codeblocks作为c/c编辑器很方便&#xff0c;无论是安装还…

svn的安装与使用

Eclipse安装SVN插件 1、下载最新的Eclipse&#xff0c;我的版本是3.7.2 indigo(Eclipse IDE for Java EE Developers)版 如果没有安装的请到这里下载安装&#xff1a;http://eclipse.org/downloads/ 2、下载SVN插件subclipse&#xff0c;安装方法有两种.那种绿色的以link方式安…

c语言实现跳动的心

本文章分为两部分&#xff1a;第一部分为实现多彩的心&#xff0c;第二部分是实现心得跳动&#xff0c;两个代码均独立运行 本篇文章转载自公众号&#xff1a; C语言程序设计基础知识 &#xff08;一&#xff09;C语言实现多彩的心 实现过程其实很简单 首先使用for循环绘制心…

structs2之多文件上传

//首先是Action部分import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.UnsupportedEncodingException; import java.util.List;import javax.servlet.ServletContext; import org.apache.struts2.ServletActionContext;i…

Linux下使用消息队实现 ATM 自动取款机功能

文章分五部分&#xff1a;需求分析、项目所需知识点、思路讲解、代码实现、功能演示 本文内容较长&#xff0c;建议是按照我自己的思路给大家讲解的&#xff0c;如果有其他问题&#xff0c;欢迎评论区讨论 文章中的代码是在linux下编译实现的&#xff0c;注意自己的环境。 &…

200行代码实现视频人物实时去除

今天在GitHub上发现了一个好玩的代码&#xff0c;短短几百行代码就实现了从复杂的背景视频中去除人物&#xff0c;不得不说这位大佬比较厉害。 这个项目只需要在网络浏览器中使用JavaScript&#xff0c;用200多行TensorFlow.js代码&#xff0c;就可以实时让视频画面中的人物对…

codeforces C. Vanya and Scales

C. Vanya and ScalesVanya has a scales for weighing loads and weights of masses w0, w1, w2, ..., w100 grams where w is some integer not less than 2(exactly one weight of each nominal value). Vanya wonders whether he can weight an item with mass m using …

菱形继承和虚继承、对象模型和虚基表

1.菱形继承&#xff08;钻石继承&#xff09;&#xff1a;两个子类继承同一父类&#xff0c;而又有子类同时继承这两个子类。例如B,C两个类同时继承A&#xff0c;但是又有一个D类同时继承B,C类。 2.菱形继承的对象模型 class A { public:int _a; };class B :public A { p…

c++虚函数和虚函数表

前言 &#xff08;1&#xff09;虚基表与虚函数表是两个完全不同的概念 虚基表用来解决继承的二义性(虚基类可以解决)。虚函数用来实现泛型编程&#xff0c;运行时多态。 &#xff08;2&#xff09;虚函数是在基类普通函数前加virtual关键字&#xff0c;是实现多态的基础 &a…

Struts.xml中Action的method与路径的三种匹配方法

原文 http://blog.csdn.net/woshixuye/article/details/7734482 首先我们有一个Action——UserAction public class UserAction extends ActionSupport { public String add() { return "add"; } public String modify() { return …