CodeForces - 5C Longest Regular Bracket Sequence(dp)

题目大意:看题目点我

    题目给你一串由‘(  ’和‘  )’组成的序列,其中如果可以在这些半括号之间插入+和1使他们变成一个合法的数学表达式的话,就称这串序列是合法的,问题目中给你的这串序列其中的合法序列最长为多少,有几个这样的最长序列?

题目思路:

      首先我们分析题目中所说的合法序列是什么,我们知道:1+1其实也是一个数学表达式,那么我们就可以知道,题目中描述的合法序列其实就是括号匹配。接下来如何求出最长的合法序列呢?

      括号匹配问题,我们知道其判断过程是通过栈来实现的,这里也是,首先遍历这串序列,遇到左括号(  就把它的位置压入栈中,遇到右括号 )就判断上一个左括号在哪里,那么这两个括号之间组成的肯定是一个合法的序列,所以如果我们用数组d[i]表示到位置i已经达到的最长合法序列的长度,设mid是从栈顶弹出的上一个左括号的位置,可以得到这样一个转移式:d[i]=d[mid]+i-mid+1,之所以加上d[mid],是因为在这串合法序列前面可能又是一个右括号,也就是说前面可能已经有了一个合法序列,要加上前面的。

题目代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<stack>
#define maxn 1000000

using namespace std;
stack<int>st;
int d[maxn];

int main(void)
{
     string a;
     cin>>a;
     memset(d,0,sizeof(d));
     int cnt=1;
     int ans=0;
     for(int i=0;i<a.size();i++)
     {
          if(a[i]=='(')
               st.push(i);
          else
          {
               if(!st.empty())//不断弹栈的操作
               {
                    int mid=st.top();
                    st.pop();
                    d[i]=d[mid-1]+i-mid+1;
                    if(ans<d[i])//如果此时得到的d[i],即序列长度大于之前得到的最大值ans,就令ans=d[i]
                    {
                         ans=d[i];
                         cnt=1;//已经更新了最长序列,此时把它的数量置为1
                    }
                    else if(ans==d[i])
                         cnt++;
               }
          }
     }
     printf("%d %d\n",ans,cnt);
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81414730