【发布时间】:2025-12-23 20:55:11
【问题描述】:
我有一个已构建的 NFA,我正在运行此方法来评估机器以查看表达式是否有效。这适用于小的正则表达式,但是当我的正则表达式的大小以及 NFA 的大小变得太大时,这个搜索会向我抛出堆栈溢出。我相当肯定这是因为我已经实现了 BFS,正在使用递归,并且可能没有很好地处理我的基本情况。
此方法接受一个表达式和一个节点(从 NFA 的起始节点开始)。首先它检查表达式的长度是否为零,如果我在一个接受节点中(节点上的布尔值),那么我返回 true。 如果表达式长度为零,但当前节点不是接受节点,则返回 false。
如果这些都不评估,那么我会得到当前节点可以使用“e”(epsilon)转换到达的所有节点的列表,并评估它们。
如果没有“e”节点,那么我从输入表达式中删除第一个字符,制作表达式的缩短子字符串(删除表达式的前面),然后查找该节点可以的节点列表使用删除的字符和简化的表达式到达。
如果这些都没有命中,那么我返回 false
一个基本的正则表达式是 (a|b)*a 一个评估表达式的例子是 aaaa 每次通过时都会减少,aaaa->aaa->aa->a->
private boolean evaluate(autoNode node, String expression)
{
if(expression.length()==0 && node.getAccept())
{
return true;
}
else if(expression.length()==0 && !node.getAccept())
{
return false;
}
String evalExp = expression.charAt(0)+""; //The first character in the expression
String redExp = expression.substring(1, expression.length());
//for each epsilon transition, evaluate it
if(node.getTransSet().contains("e"))
{
//if this node has an "e" transition then...
ArrayList<autoNode> EpsilonTransMap = node.getPathMap("e");
//The above ArrayList is a list of all the nodes that this node can reach
//using the "e" / epsilon transition
for(autoNode nodes : EpsilonTransMap)
{
if(evaluate(nodes, expression))
{
return true;
}
}
}
//for each transition on that key evaluate it
if(node.getTransSet().contains(evalExp))
{
//if this node has a transition from the front of the expression then...
ArrayList<autoNode> TransitionKeyMap = node.getPathMap(evalExp);
//The above ArrayList is a list of all the nodes that this node can reach
//on a transition equal to the "key" removed from the front of the expression String
for(autoNode nodes : TransitionKeyMap)
{
if(evaluate(nodes, redExp))
{
return true;
}
}
}
return false;
}
我知道我可能使用 bfs 搜索而不是 dfs 导致了我自己的问题。我想知道是否有人可以帮助我解决这个问题并通过一次发生太多事情来避免堆栈溢出。因为 while (a|b)*a 可以评估得很好......
((aa)+|(bb)+|(cc)+)(ba)(ca)
创建一个相当大的 NFA,这会在评估时导致堆栈溢出: “一个”
任何不会导致我完全放弃该方法的事情都将非常好并且不胜感激。
【问题讨论】:
-
也许,您可以尝试将 NFA 转换为 DFA ,以减少回溯。