构造与正则表达式对应的NFA
接上一节
https://blog.csdn.net/greatyoulv/article/details/104186619
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
‘’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
public class regexNFA {
public static void main(String[] args) {
// TODO Auto-generated method stub
String txt = "abac";
String regex = "aba*c";
boolean result = isMatch(txt, regex);
System.out.println(result);
}
public static boolean isMatch(String s, String p) {
char[] sc = s.toCharArray();
char[] pc = p.toCharArray();
//图的状态数比正则字符数多1(起始状态)
int m = pc.length + 1;
boolean[][] graph = new boolean[m][m];
for (int i = 0; i < m - 1; i++) {
//存放当前位
int lp = i;
// 当下一位为闭包操作(m-1是正则串的长度,pc[m-2]指向正则串的最后一位,< m-2指向倒数第二位)
if (i< m - 2 && pc[i + 1] == '*') {
// 进行双向链接
graph[lp][i + 1] = true;
graph[i + 1][lp] = true;
}
// 特定符号直接链接下一位
if (pc[i] == '*') {
graph[i][i + 1] = true;
}
}
// 打印图
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
System.out.print(graph[i][j] + " ");
}
System.out.println();
}
// 深度搜索第一个顶点的可达顶点
boolean[] mark = dfs(graph, 0);
// 打印访问标记
for (int i = 0; i < mark.length; i++) {
System.out.print(mark[i] + "-");
}
System.out.println();
// 遍历字符串
for (int i = 0; i < sc.length; i++) {
boolean[] match = new boolean[m];
for (int j = 0; j < m; j++) {
// 标记当前访问点
if (mark[j]) {
// 标记最后一位
if (j == m - 1) {
continue;
}
// 当前标志访问点的值点为(".")或与给定字符串相匹配的第一个字符
if (pc[j] == sc[i] || pc[j] == '.') {
// 无需读入字符直接状态转移到下一位
match[j + 1] = true;
}
}
}
// 对状态转移到的下一位进行深度搜索
mark = dfs(graph, match);
// 打印访问标记
System.out.println(i);
for (int k = 0; k < mark.length; k++) {
System.out.print(mark[k] + "--");
}
System.out.println();
}
return mark[m - 1];
}
private static boolean[] dfs(boolean[][] graph, int s) {
boolean[] re = new boolean[graph.length];
doDfs(graph, re, s);
return re;
}
private static boolean[] dfs(boolean[][] graph, boolean[] mark) {
boolean[] re = new boolean[graph.length];
for (int i = 0; i < mark.length; i++) {
if (mark[i]) {
doDfs(graph, re, i);
}
}
return re;
}
private static void doDfs(boolean[][] graph, boolean[] mark, int v) {
mark[v] = true;
for (int i = 0; i < graph.length; i++) {
if (!mark[i] && graph[v][i]) {
doDfs(graph, mark, i);
}
}
}
}
参考链接:
https://blog.csdn.net/weixin_41427400/article/details/80958777