AcWing 150

原题链接

题意

给出1个长度为n的括号序列,大中小6种字符。

美观的括号序列定义为:

(1) 空序列;

(2) 若括号序列A是美观的,则括号序列 (A)、[A]、{A} 也是美观的;

(3) 若括号序列A、B都是美观的,则括号序列AB也是美观的。

例如 [(){}]() 是美观的括号序列,而)({)[}]( 则不是。

求长度最大的美观序列长度。

\(1 \leq n \leq 10^5\)

本人题解

总体思考:嵌套括号序列很有子问题的味道

不妨简化1下问题。

当只有嵌套1种情况时,怎么做?找到相邻的括号(形如()[]{})向外扩展求得嵌套的极大区间。

能够合并区间时,怎么做?区间恰好相邻,则可以自然地相连。

然后,可以在连接的产物外面继续套括号;若将连接的产物看作已经完成的子问题而直接删去,则相当于再次执行第1步:直接匹配括号。

不难发现,这是1个循环往复的过程。统一化的表达就是:每次找到1对直接匹配的相邻括号,删去它。(即令前驱指向后继,并将匹配位置移向前驱继续尝试匹配)。

完成所有删除操作后,存在的元素中,两两下标差值最大值即为所求。

删除操作使用链表实现。时间复杂度\(O(n)\)。[代码见此](https://github.com/littlewyy/OI/blob/master/AcW 150.cpp)

普遍解法

从左到右逐步考虑,第\(i\)个元素前的待匹配序列可用1个栈来维护。若\(i\)与栈顶能够匹配,则弹出栈顶元素。

归结起来,正是由于括号序列的递归性和完整性,使用进行动态维护最为恰当。

括号序列的外延

假设只有1种括号(),那么在构造括号序列的过程中,只需要满足任意时刻左括号个数大于等于右括号个数。

原因:只有1种括号,因而不管括号怎样”交叉“放置,都可以视为嵌套/相连。例如\([(])\)不是括号序列,但\((())\)是括号序列。故只要右括号左边有空闲的左括号,就一定可以匹配成功;否则匹配失败,一定不成功。

posted @ 2019-08-05 19:26  littlewyy  阅读(113)  评论(0编辑  收藏  举报