题目描述:
一个括号序列是指一个由'(', ')', '[', ']'四种字符组成的字符串。
一个只包含数字,加号'+',和上述四种括号的合法算数表达式,去掉数字和加号之后得到的括号序列成为合法的括号序列。我们定义空串也是合法的括号序列。
例如(1) + [2], ([3]), 4 + [5]相应的括号序列 "()[]", "([])", "[]"都是合法的括号序列。而(6 + 7], [8 + ((9对应的"(]", "[(("则是非法的。
字符串
s0s1s2⋯s|s|−1
的子串
s[l,r](0≤ l≤r<|s|)
是指
slsl+1⋯sr
。
现在给定一个括号序列,请找出其中的一个子串,使得这个子串是合法的括号序列,且包含的'['数量最多。
输入:
一个括号序列s。 1≤|s|≤5×105
输出:
第一行,答案要求的子串中包含'['的数量。
如果答案是0,输出到此为止,否则:
第二行,两个整数l, r。表示子串第一个字符的位置和最后一个字符的位置。
如果有多个满足条件的字符串,请输出使得子串长度最大的答案。如果长度最大的仍有多个,请输出r最大的。
思路:
首先说一下大思路:
处理出从字符串s每一个位置i开始的最长的合法串,用ans[i]记录,其中ans[i].l== i,ans[i].r 为从i开始最长合法串的最右端,ans[i].cnt = r - l + 1;
用数组num[x]表示前x个元素中 ‘[’ 出现的次数,这个可以直接循环一遍得到;
则对于每个位置i,num[ans[i].r] - num[ans[i].l - 1]表示从i开始的最长合法串中的'['的个数;
那么关键是怎么得到ans数组?
处理括号问题,常用栈,我们用数组a模拟一个栈,用cur来表示栈顶指针,栈中存储结构体node1,a[cur].ch表示栈顶的字符,a[cur].pos表示栈顶字符是字符串s中的第pos个元素,如果栈顶是'('且新加入')',那么弹出栈顶元素(栈顶为'['时类似),第i次循环加入s[i]之后,栈顶元素在s中位置p是a[cur].pos,那么如果i - p大于0就把ans[p+1].r置为i,ans[p+1].cnt置为i - p,如此就可以O(n)维护ans
AC代码(注意别被查重!!!):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxn 500005
int Max(const int a , const int b)
{
return a < b ? a : b ;
}
char s[maxn] ;
int num[maxn];
struct node1
{
char ch ;
int pos ;
}a[maxn];
struct node2
{
int cnt , l , r ;
}ans[maxn];
int main()
{
scanf("%s" , s + 1 ) ;
int len = strlen( s + 1 ) , cur = 0 , i ;
num[0] = 0;
for(i = 1 ; i<= len ; i++){
num[i] = num[i - 1] + (s[i] == '[') ;
}
for( i = 1 ; i<= len ; i++){
ans[i].cnt = 0;
ans[i].l = i ;
}
for( i = 1 ; i <= len ; i++){
struct node1 st1 = {s[i] , i};
if((a[cur].ch=='(' &&st1.ch ==')')||(a[cur].ch=='[' &&st1.ch ==']')){
--cur ;
}
else{
a[++cur] = st1 ;
}
int x = a[cur].pos ;
if(ans[x+1].cnt < i - x){
ans[x+1].cnt = i - x ;
ans[x+1].r = i;
}
}
int res = 0 , ansl , ansr ;
for(i = len ; i > 0 ; i--){
if(ans[i].cnt){
int comp = num[ans[i].r] - num[ans[i].l - 1] ;
if(comp > res){
res = comp;
ansl = ans[i].l;
ansr = ans[i].r;
}
else if(comp == res){
if(ans[i].r - ans[i].l > ansr - ansl){
ansl = ans[i].l;
ansr = ans[i].r;
}
}
}
}
printf("%d\n",res);
if(res){
printf("%d %d\n",ansl-1,ansr-1);
}
return 0;
}