DFA最小化之JAVA实现
2010-02-20 17:39
946 查看
一.简介
在解析正则表达式的算法中,有穷自动机(DFA)得到广泛的应用,为正则表达式构建DFA的常用方法有二种:
一种是通过子集构造法生成一个中间NFA生成DFA,
另外一种就是通过一个FOLLOWPOS的推导法直接从正则得到DFA.
这二种方法生成的DFA有可能包含了一些多余的转换,这个时候就需要消除掉一些多余的状态,下面是DFA最小化算法的JAVA实现:
在解析正则表达式的算法中,有穷自动机(DFA)得到广泛的应用,为正则表达式构建DFA的常用方法有二种:
一种是通过子集构造法生成一个中间NFA生成DFA,
另外一种就是通过一个FOLLOWPOS的推导法直接从正则得到DFA.
这二种方法生成的DFA有可能包含了一些多余的转换,这个时候就需要消除掉一些多余的状态,下面是DFA最小化算法的JAVA实现:
package chapter3; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * 算法 3.39 最小化一个DFA的状态数 * @author Administrator * */ public class Arithmetic_3_39 { /** * 输入一个DFA D * @param d DFA状态转换表 * @param S 状态集合 * @param E 输入字符表 * @param s 开始状态 * @param F 接受状态集 * @return 一个DFA D', 它和D接受相同的语言, 且输入状态数最少 */ public int[][] convert(int[][] d, Set<Integer> S, char[] E, int s, Set<Integer> F) { // 首先用接受状态组和非接受状态组划分 PI Set<Set<Integer>> PI = new HashSet<Set<Integer>>(); // 计算 S - F S.removeAll(F); PI.add(F); PI.add(S); // 最初, 令PInew = PI Set<Set<Integer>> PInew = new HashSet<Set<Integer>>(); // TODO 解决浅复制带来的问题 PInew.addAll(PI); while (true) { // 对PI中的每个组G for (Iterator<Set<Integer>> it = PI.iterator(); it.hasNext(); ) { List<Object> groupList = new ArrayList<Object>(); Set<Integer> G = it.next(); // 使用字符表测试G的元素 // 对于字符表的每个输入a for (int i = 0; i < E.length; i++) { Map<Integer, Set<Integer>> groupMap = new HashMap<Integer, Set<Integer>>(); char a = E[i]; for (Iterator<Integer> sIt = G.iterator(); sIt.hasNext(); ) { int stat = sIt.next(); // 从状态S出发 沿着a能够到达的状态 int tar = d[stat][a]; // 获取目标状态在PI中的位置 int idx = getElelementIdx(PI, tar); Set<Integer> group = groupMap.get(idx); if (group == null) { group = new HashSet<Integer>(); groupMap.put(idx, group); } group.add(stat); } groupList.add(groupMap); } // 在PInew中将G替换为对G进行分组得到的那些小组 PInew.remove(G); PInew.addAll(setListPoly(groupList)); } // 判断2个集合组是否相等 if (!isTwoSetGrpEqual(PI, PInew)) { PI.clear(); PI.addAll(PInew); } else { break; } } // TODO 步骤4 for (Iterator<Set<Integer>> it = PI.iterator(); it.hasNext(); ) { Set<Integer> set = it.next(); // 令S1是PI组中某个G的代表 for (Iterator<Integer> sIt = set.iterator(); sIt.hasNext(); ) { int s1 = sIt.next(); while (sIt.hasNext()) { // 用S1替换SWP int swp = sIt.next(); for (int i = 0; i < d.length; i++) { for (int j = 0; j < d[i].length; j++) { if (d[i][j] == swp) { d[i][j] = s1; } } } // 删除SWP的转换函数 d[swp] = new int[]{}; } } } return d; } /** * 获取某个元素在集合组中的索引 * @param set * @param element * @return */ private int getElelementIdx(Set<Set<Integer>> set, int element) { int idx = 0; for (Iterator<Set<Integer>> it = set.iterator(); it.hasNext(); ) { Set<Integer> g = it.next(); if (g.contains(element)) { // TODO 检查HASHCODE 是否代表了集合的位置 return idx; } idx++; } return -1; } // 计算集合组聚合的结果 @SuppressWarnings("unchecked") private Set<Set<Integer>> setListPoly(List<Object> oriSetList) { Set<Set<Integer>> result = new HashSet<Set<Integer>>(); if (oriSetList.size() > 0) { // 读取第一个集合组 Map<Integer, Set<Integer>> groupMap = (Map<Integer, Set<Integer>>)oriSetList.get(0); for (Iterator<Integer> it = groupMap.keySet().iterator(); it.hasNext(); ) { result.add(groupMap.get(it.next())); } for (int i = 1; i < oriSetList.size(); i++) { // 获取中间集合 Map<Integer, Set<Integer>> midMap = (Map<Integer, Set<Integer>>)oriSetList.get(i); List<Set<Integer>> midSetList = new ArrayList<Set<Integer>>(); for (Iterator<Integer> it = midMap.keySet().iterator(); it.hasNext(); ) { midSetList.add(midMap.get(it.next())); } // 开始计算 // 运算结果 List<Set<Integer>> calcResult = new ArrayList<Set<Integer>>(); for (Iterator<Set<Integer>> it = result.iterator(); it.hasNext(); ) { Set<Integer> srcSet = it.next(); for (int k = 0; k < midSetList.size(); k++) { // 计算2个集合的交集 Set<Integer> mixed = getSetMixed(srcSet, midSetList.get(k)); // 如果结果不为空 if (!mixed.isEmpty()) { // 保存运算结果 calcResult.add(mixed); } } } // 将计算结果替换result result.clear(); result.addAll(calcResult); } } return result; } // 计算二个集合的交集 private Set<Integer> getSetMixed(Set<Integer> set1, Set<Integer> set2) { Set<Integer> mixed = new HashSet<Integer>(); for (Iterator<Integer> it = set1.iterator(); it.hasNext(); ) { int emu = it.next(); if (set2.contains(emu)) { mixed.add(emu); } } return mixed; } /** * 判断2个集合组是否相等 * @param setGrp1 * @param setGrp2 * @return */ private boolean isTwoSetGrpEqual(Set<Set<Integer>> setGrp1, Set<Set<Integer>> setGrp2) { boolean same = false; int matchCounts = 0; if (setGrp1.size() == setGrp2.size()) { for (Iterator<Set<Integer>> it = setGrp1.iterator(); it.hasNext(); ) { Set<Integer> set1 = it.next(); for (Iterator<Set<Integer>> it2 = setGrp2.iterator(); it2.hasNext(); ) { Set<Integer> set2 = it2.next(); if (set2.equals(set1)) { matchCounts++; } } } if (matchCounts == setGrp1.size()) { same = true; } } return same; } } // 测试: package test; import java.util.HashSet; import java.util.Set; import chapter3.Arithmetic_3_39; public class TestCase { public static void main(String[] args) { new TestCase().test_339(); } public void test_339() { // DFA的转换表 int[][] d = {{}, {2, 3}, {2, 4}, {2, 3}, {2, 5}, {2, 3}}; // 输入状态集合 Set<Integer> S = new HashSet<Integer>(); S.add(1); S.add(2); S.add(3); S.add(4); S.add(5); // 输入字符 char[] E = {0, 1}; int s = 1; Set<Integer> F = new HashSet<Integer>(); F.add(5); Arithmetic_3_39 a339 = new Arithmetic_3_39(); a339.convert(d, S, E, s, F); } }
相关文章推荐
- 编译原理(二) NFA的确定化及DFA的最小化的算法及C++实现
- 实现一个 DFA 正则表达式引擎 - 4. DFA 的最小化
- Java DFA算法实现敏感词过滤
- 用JAVA实现程序最小化到托盘区
- Java JFrame设计及最小化到系统托盘的实现
- DFA算法实现Java敏感词过滤
- java最小化到托盘显示图标实现
- Java实现DFA算法 实现敏感词过滤
- java Swing 实现将系统最小化到系统托盘
- 简单实现java DFA算法对敏感词过滤
- java实现页面最小化后桌面右下角出现提示框(跟QQ提示一样)
- Java实现DFA算法对敏感词、广告词过滤功能
- java实现敏感词过滤 dfa算法实现
- 【Java】聊天过滤 DFA算法的Java实现
- Java使用DFA算法实现敏感词过滤
- [置顶] DFA最小化 -- Hopcroft算法 Python实现
- Java实现DFA算法对敏感词、广告词过滤功能示例
- java swing 点击关闭按钮最小化到系统托盘的实现
- Java实现DFA算法进行敏感词过滤
- NFA(子集算法,DFA最小化)代码实现