(CodeForces - 5C)Longest Regular Bracket Sequence

10 篇文章 0 订阅

(CodeForces - 5C)Longest Regular Bracket Sequence

time limit per test:2 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output

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”.

Examples

input

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

output

6 2

input

))(

output

0 1

题目大意:题目意思很简单,就是给以一串括号,要求最长合法括号子序列。

思路:这个题目可以从两种角度考虑。
方法一:这是典型的括号题,括号题一般都可以用栈+dp解决。设f[i]表示位置为i的右括号结尾的最长合法括号子序列的长度,则易得:
f[i]=f[tmp-1]+i-tmp+1,其中tmp表示与位置为i的右括号匹配的左括号的位置(可以用栈记录)。
方法二:贪心。我们从左到右依次扫一遍括号串,碰到左括号cnt++,碰到右括号,并且此时cnt不为0,则说明该右括号有与之匹配的左括号,是合法的,记vis[i]为1;同理再从右到左扫一遍括号,记录合法的左括号,令vis[i]为1。而我们要做的就是统计连续1出现的个数的最大值,这只要从左到右扫一遍即可,所以该算法是O(n)的。

栈+dp实现代码

#include<cstdio>
#include<cstring>
#include<stack> 
using namespace std;

const int maxn=1000005;
char s[maxn];
int f[maxn];
stack<int> st; 

int main()
{
    scanf("%s",s+1);
    int ans=0,sum=0;
    int len=strlen(s+1);
    memset(f,0,sizeof(f));
    for(int i=1;i<=len;i++)
    {
        if(s[i]=='(') st.push(i);
        else 
        {
            if(!st.empty())
            {
                int t=st.top();
                st.pop();
                f[i]=f[t-1]+i-t+1;
                if(ans<f[i]) ans=f[i],sum=1;
                else if(ans==f[i]) sum++;
            }
        }
    }
    if(ans==0) sum=1;
    printf("%d %d\n",ans,sum);
    return 0;
} 

贪心实现代码

#include<cstdio>
#include<cstring>
using namespace std;

const int maxn=1000005;
char s[maxn];
bool vis[maxn];

int main()
{
    scanf("%s",s);
    int len=strlen(s);
    int cnt=0;
    memset(vis,false,sizeof(vis));
    for(int i=0;i<len;i++)
    {
        if(s[i]=='(') cnt++;
        if(s[i]==')')
        {
            if(cnt)
            {
                vis[i]=true;
                cnt--;
            }
        }
    }
    cnt=0;
    for(int i=len-1;i>=0;i--)
    {
        if(s[i]==')') cnt++;
        if(s[i]=='(')
        {
            if(cnt)
            {
                vis[i]=true;
                cnt--;
            } 
        }
    }
    int ans=0,sum=0;//ans表示最长匹配括号串的括号个数,sum表示最长匹配括号串一共有几个 
    cnt=0;
    for(int i=0;i<len;i++)
    {
        if(vis[i]) cnt++;
        else cnt=0;
        if(ans<cnt) ans=cnt,sum=1;
        else if(ans==cnt) sum++;
    }
    if(ans==0) sum=1;//没找到匹配括号串,则按题目要求给sum赋值1
    printf("%d %d\n",ans,sum);
    return 0; 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值