【CodeForces 5C】【贪心】【dp】Longest Regular Bracket Sequence

Longest Regular Bracket Sequence

Time Limit: 2000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u

Description

This is yet another problem dealing with regular bracket sequences.
We should remind you that a bracket sequence is called regular, if by inserting «+» and «1» into it we can get a correct mathematical expression. For example, sequences «(())()», «()» and «(()(()))» are regular, while «)(», «(()» and «(()))(» are not.
You are given a string of «(» and «)» characters. You are to find its longest substring that is a regular bracket sequence. You are to find the number of such substrings as well.

Input

The first line of the input file contains a non-empty string, consisting of «(» and «)» characters. Its length does not exceed 106.

Output

Print the length of the longest substring that is a regular bracket sequence, and the number of such substrings. If there are no such substrings, write the only line containing “0 1”.

Samples

Input1

)((())))(()())

Output1

6 2

Input2

))(

Output2

0 1

Source

Codeforces Beta Round #5

这个题有两个做法,一个是贪心(很复杂),一个是dp(超简单),dp orz hzx

先说一下贪心,直接跑一遍是肯定过不了的,可以正反跑两边,遇到正括号就++,反括号就–,然后如果小于0就重置计数器,等于0就更新答案
但是这样子只能跑出来最大值,个数很萎,还要跑出最大值再根据这个来把数目跑出来,还要返回检验,感觉比较慢,写起来也很复杂吗,但是可以过
然后就是dp,这里运用栈来辅助,读入右括号事,自动去匹配前一个未匹配的左括号,然后和它匹配更新答案

代码见下,显示贪心,我写的很复杂不要吐槽了:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define clrmax(x)  memset(x,127,sizeof(x))

using namespace std;

inline int read()
{
    char c;
    int ret=0;
    while(!(c>='0'&&c<='9'))
        c=getchar();
    while(c>='0'&&c<='9')
    {
        ret=(c-'0')+(ret<<1)+(ret<<3);
        c=getchar();
    }
    return ret;
}

int ans,tim,mx,now,sta,r,l,lt,rt;
char c,s[1000005];

void work(int x)
{
    if(c=='(')now+=x;
         else now-=x;
    ans++;
    if(now==0)mx=max(mx,ans);
    if(now<0)
    {
        ans=0;
        now=0;
    }
}

int main()
{
    freopen("in.txt","r",stdin);
    while(c=getchar())
    {
        if(c!='('&&c!=')')break;
        s[++sta]=c;
        work(1);
    }
    ans=now=0;
    for(int i=sta;i>=1;i--)
    {
        c=s[i];
        work(-1);
    }
    if(mx==0)
    {
        cout<<"0 1";
        return 0;
    }
    for(int i=1;i<=sta;i++)
    {
        c=s[i];
        if(c=='(')l++;
        else r++;
        if(i<mx)continue;
        int j=i-mx+1;
        if(s[j]=='('&&s[i]==')'&&l-lt==r-rt)
        {
            int now=0,b=1;
            for(int k=j;k<=i;k++)
            {
                if(s[k]=='(')now++;
                else now--;
                if(now<0)
                {
                    b=0;
                    break;
                }
            }
            if(b)
            {
                int temp=i;
                c=s[j];
                if(c=='(')lt++;
                else rt++;
                for(i=temp+1;i<=temp+mx;i++)
                {
                    j=i-mx+1;
                    c=s[i];
                    if(c=='(')l++;
                    else r++;
                    c=s[j];
                    if(c=='(')lt++;
                    else rt++;
                }
                tim++;
                i--;
                continue;
            }

        }
        c=s[j];
        if(c=='(')lt++;
        else rt++;

    }
    cout<<mx<<' '<<tim;
    return 0;
}

接着是dp:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define clrmax(x)  memset(x,127,sizeof(x))

using namespace std;

inline int read()
{
    char c;
    int ret=0;
    while(!(c>='0'&&c<='9'))
        c=getchar();
    while(c>='0'&&c<='9')
    {
        ret=(c-'0')+(ret<<1)+(ret<<3);
        c=getchar();
    }
    return ret;
}

#define M 1000005

int f[M],mx,tim,n;
stack<int>S;

int main()
{
    char c;
    while(c=getchar())
    {
        n++;
        if(c!='('&&c!=')')
        {
            if(mx)cout<<mx<<' '<<tim;
            else cout<<"0 1";
            return 0;
        }
        if(c=='(')S.push(n);
        else
        {
            if(!S.empty())
            {
                int t=S.top();S.pop();
                f[n]=f[t-1]+n-t+1;
                if(f[n]>mx)
                {
                    mx=f[n];
                    tim=1;
                }
                else if(f[n]==mx)tim++;
            }

        }
    }
}

大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值