一种方法是让第一个线程从字符串的开头开始,并使用堆栈来处理字符串的前半部分。第二个线程从字符串的末尾开始,反向处理字符串的后半部分。
当两个线程都完成了第一个阶段时,第一个线程将第二个线程的堆栈视为字符串的延续。
因此,例如,您有:
[({(())}[])]
线程 1 得到[({(()
,线程 2 得到)}[])]
他们每个人都完成了他们的处理,产生了这两个堆栈(左边是堆栈的顶部):
`({([` `)})]`
然后线程 1 可以将线程 2 的堆栈变成一个字符串(或将堆栈视为一个字符串,一次弹出一个字符),并继续其处理。
想想看,当两个线程处理完它们的一半字符串时,两个堆栈必须是相同的长度,并且它们是彼此的镜像。第一个线程的堆栈将只包含开始分隔符(即'('、'['或'{'),而第二个线程的堆栈将只包含关闭分隔符。所以在两个线程完成了它们的一半处理后,最后一部分很简单:
while (stack1.Count > 0 && stack2.Count > 0)
{
left = stack1.Pop();
right = stack2.Pop();
if (!delimiters_match(left, right))
{
// error!
}
}
请注意,在处理过程中的任何时候,任何一个线程都可能检测到错误。例如,给定:
([){})[)
第一个线程知道第三个字符发生了错误,因为您不能)
立即 follow [
。同样,第二个线程知道[
(next to last character) 有错误,因为您不能[
立即使用 before )
。
但是有些错误只能在第二阶段检测到。例如:
({[}])
左右子串是有效的,但组合起来却不是。