bit程序设计 括号序列 栈+前缀和

来源:互联网 发布:百度时序数据库 编辑:程序博客网 时间:2024/06/08 10:46

题目描述:

一个括号序列是指一个由'(', ')', '[', ']'四种字符组成的字符串。

一个只包含数字,加号'+',和上述四种括号的合法算数表达式,去掉数字和加号之后得到的括号序列成为合法的括号序列。我们定义空串也是合法的括号序列。

例如(1) + [2], ([3]), 4 + [5]相应的括号序列 "()[]", "([])", "[]"都是合法的括号序列。而(6 + 7], [8 + ((9对应的"(]", "[(("则是非法的。

字符串s0s1s2s|s|1的子串s[l,r](0 lr<|s|)是指slsl+1sr

现在给定一个括号序列,请找出其中的一个子串,使得这个子串是合法的括号序列,且包含的'['数量最多。


输入:

一个括号序列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 500005int 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;}


0 0