我没使用DP,刚刚好想起了之前看黄色算法的正则表达式,于是灵光一闪,想用构造NFA和图遍历的方法来解这道题,好吧感觉就是抄了一遍算法书构造了图,和书上代码基本类似,ac这道题画了17ms,理了一下思路:代码放下
import java.util.LinkedList;
import java.util.Stack;
public class RegularExpressionMatching {
public RegularExpressionMatching() {
// TODO Auto-generated constructor stub
}
public boolean isMatch(String s, String p) {
NFA nfa = new NFA(p);
return nfa.recognizes(s);
}
}
class Digraph{
private final int V;
private int E;
private LinkedList<Integer>[] adj;
public Digraph(int V){
this.V =V;
this.E = 0;
adj = new LinkedList[V];
for(int v=0;v<V;v++){
adj[v] = new LinkedList<>();
}
}
public int V(){
return V;
}
public int E(){
return E;
}
public void addEdge(int v,int w){
adj[v].add(w);
E++;
}
public Iterable<Integer> adj(int v){
return adj[v];
}
public Digraph reverse(){
Digraph R = new Digraph(V);
for (int v = 0; v < V; v++) {
for(int w:adj[v]){
addEdge(w, v);
}
}
return R;
}
}
class DirectedDFS{//算法4.4 4.2.3
private boolean[] marked;
public DirectedDFS(Digraph G,int s){
marked = new boolean[G.V()];
dfs(G,s);
}
public DirectedDFS(Digraph G,Iterable<Integer> sources){
marked = new boolean[G.V()];
for(int s:sources)
if(!marked[s])dfs(G,s);
}
private void dfs(Digraph G,int v){
marked[v] = true;
for(int w:G.adj(v)){
if(!marked[w]){
dfs(G,w);
}
}
}
public boolean marked(int w){
return marked[w];
}
}
class NFA{
private char[] re;
private Digraph G;
private int M;
public NFA(String regexp){
Stack<Integer> ops = new Stack<Integer>();
re = regexp.toCharArray();
M =re.length;
G = 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();
G.addEdge(lp, or+1);
G.addEdge(or, i);
}
else lp=or;
}
if(i<M-1&&re[i+1] == '*'){
G.addEdge(lp, i+1);
G.addEdge(i+1, lp);
}
if(re[i] == '('||re[i]=='*'||re[i]==')'){
G.addEdge(i, i+1);
}
}
}
public boolean recognizes(String txt){
LinkedList<Integer> pc = new LinkedList<>();
DirectedDFS dfs = new DirectedDFS(G, 0);
for (int v = 0; v <G.V(); v++) {
if(dfs.marked(v))pc.add(v);
}
for(int i =0;i<txt.length();i++){
LinkedList<Integer> match = new LinkedList<>();
for(int v:pc){
if(v<M){
if(re[v] == txt.charAt(i)||re[v] =='.')
match.add(v+1);
}
}
pc = new LinkedList<>();
dfs = new DirectedDFS(G, match);
for(int v=0;v<G.V();v++){
if(dfs.marked(v))pc.add(v);
}
}
for(int v:pc)if(v==M) return true;
return false;
}
}
1546

被折叠的 条评论
为什么被折叠?



