NFA.java
package cn.denghanxi.s54;
import edu.princeton.cs.algs4.Bag;
import edu.princeton.cs.algs4.Digraph;
import edu.princeton.cs.algs4.DirectedDFS;
import edu.princeton.cs.algs4.Stack;
/**
* 非确定有限状态自动机
*/
public class NFA {
private char[] re; //匹配转换
private Digraph digraph; //epsilon转换 空转换
private int m; //状态数量
public NFA(String regexp) {
Stack<Integer> ops = new Stack<>();
re = regexp.toCharArray();
m = re.length;
digraph = new Digraph(m + 1);
for (int i = 0; i < m; i++) {
int lp = i;
if (re[i] == '(' || re[i] == '|') {
ops.push(i);
} else if (re[i] == ')') {
int or = ops.pop();
if (re[or] == '|') {
lp = ops.pop();
digraph.addEdge(lp, or + 1);
digraph.addEdge(or, i);
} else {
lp = or;
}
}
if (i < m - 1 && re[i + 1] == '*') {
digraph.addEdge(lp, i + 1);
digraph.addEdge(i + 1, lp);
}
if (re[i] == '(' || re[i] == '*' || re[i] == ')') {
digraph.addEdge(i, i + 1);
}
}
}
public boolean recognizes(String txt) {
Bag<Integer> pc = new Bag<>();
DirectedDFS dfs = new DirectedDFS(digraph, 0);
for (int v = 0; v < digraph.V(); v++) {
if (dfs.marked(v)) pc.add(v);
}
for (int i = 0; i < txt.length(); i++) {
Bag<Integer> match = new Bag<>();
for (int v : pc)
if (v < m)
if (re[v] == txt.charAt(i) || re[v] == '.')
match.add(v + 1);
pc = new Bag<>();
dfs = new DirectedDFS(digraph, match);
for (int v = 0; v < digraph.V(); v++)
if (dfs.marked(v)) pc.add(v);
}
for (int v : pc) if (v == m) return true;
return false;
}
}