洛谷P1944 最长括号匹配
【题意】:
【两个定义】:
-
括号匹配的字符串:
-
(),[]
是括号匹配的字符串。
-
若 A
是括号匹配的串,则 (A),[A]
是括号匹配的字符串。
-
若 A,B
是括号匹配的字符串,则 AB
也是括号匹配的字符串。
例如:(),[],([]),()()
都是括号匹配的字符串,而 ][,[(])
则不是。
-
字符串 A 的子串是指由 A 中连续若干个字符组成的字符串。
例如,A,B,C,ABC,CAB,ABCABC
都是 ABCABC
的子串。空串是任何字符串的子串。
【问题描述】: 给定一个仅由 ()[]
构成的字符串 A,求其最长的括号匹配子串,要求输出该子串。如有多解,输出开始字符所在位置最靠前的一个。1≤∣A∣≤1×106。
【思路】:
记 fi 表示考虑第 i 个字符时的最长括号匹配子串,要求该子串也必须以 i 结尾。即 Ai−fi+1..i 是括号匹配子串,且 fi 最大。
接下来就开始考虑如何转移:
-
当 Ai 是 (
或 [
时,fi=0。为什么?因为以 i 结尾的子串肯定不是括号匹配子串。
-
当 Ai 是 )
或 ]
时,我们的任务是求出一个 k,使得 Ak+1,i−1 是括号匹配子串且 Ak,i 也是括号匹配子串,同时,k 必须尽可能的小(这样长度才能大)。
等等,因为 fi−1 表示 Ai−fi−1..i−1 是一个括号匹配子串,那么我们是不是可以贪心的让 Ai−1−fi−1 和 Ai 匹配呢?
答案是肯定的。因为如果 Ai−1−fi−1 和 Ai 匹配的话,k=i−1−fi−1 肯定是最优的。为什么?首先,Ai−1−fi−1..i 肯定是一个括号匹配子串。其次,如果我们在往内扩展的话,肯定不优,如果我们往外可以扩展到另一个 k′ 的话,那么 fi−1 的值就肯定错了(因为 Ak′+1..i−1 肯定也是括号匹配子串),不符,排除。
如果 Ai−1−fi−1 和 Ai 不匹配的话,fi=0。为什么?因为往内扩展时也肯定没有一个地方可以让它到 i 的子串成为括号匹配子串。大家可以画个图或想象一下。
于是,我们就可以 O(∣A∣) 完成这题啦!!!
【代码】:
N>1×106 即可。