Code Forces #5C

来源:互联网 发布:德胡安 布莱尔数据 编辑:程序博客网 时间:2024/04/27 15:27

给一个只包含括号的字符串,求其中最长的匹配的括号子串的长度和这个长度子串的数量

每一个左括号所匹配的右括号是他右边离他最近的并且没有被更近的左括号匹配的右括号。。。

将所有的右括号的下标放进set,然后从最右端的左括号开始向左扫,在set里二分离他最近的右括号,如果有,标记(左括号下表a,右括号下标b,那么vis[a]=b,vis[b]=a)并从set中去掉这个右括号的下标。

这样就可以找到每个括号所匹配的括号的位置。

如果连续一段的vis值都存在的话,说明这一段括号是匹配的。找最长的连续一段的长度即可。

#include<stdio.h>#include<string.h>#include<set>#include<map>using namespace std;char str[1111111];int vis[1111111];int main(){    while(scanf("%s",&str)!=EOF){        memset(vis,-1,sizeof(vis));        map<int,int>mp;        set<int>s;        int len=strlen(str);        int edl,st_r=-1;        for(int i=0;i<len;i++){            if(str[i]=='(')edl=i;            if(str[i]==')'){                s.insert(i);            }        }        set<int>::iterator it;        for(int i=edl;i>=0;i--){            if(str[i]!='(')continue;            it=s.lower_bound(i);            if(it==s.end()){                if(*it>i){                    vis[i]=*it,vis[*it]=i;                    s.erase(it);                }else continue;            }else {                vis[i]=*it,vis[*it]=i;                s.erase(it);            }        }        int tot=0,mx=0;        for(int i=0;i<len;i++){            if(vis[i]!=-1)tot++;            else {                if(tot>mx)mx=tot;                mp[tot]++;                tot=0;            }        }        if(tot>mx)mx=tot;        if(tot)mp[tot]++;        if(mx==0){            printf("0 1\n");continue;        }        printf("%d %d\n",mx,mp[mx]);    }    return 0;}


0 0