• codeforces 5C


    C. 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,转移方程不知从何推起。。。

    题意:给一个字符串,有左括号和右括号。求满足括号配对的最长子串的长度及个数。

    解题思路1:求dp转移方程。遇到左括号就记录下来,遇到右括号,就把与之最近的左括号取出来(如果有的话)与右括号配对,此时这段的长度是右括号位置与左括号位置之差,记为dp[t]。
    此时的这个长度,再加上一个相邻串的长度即dp[t-1]的长度,就是目前这个串的长度啦,所以转移方程就是dp[t]=dp[t-1]+i-t+1;
    附ac代码:
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <stack>
     6 using namespace std;
     7 const int maxn = 1e6+5;
     8 int dp[maxn];
     9 stack<int>q;
    10 int main() {
    11     ios::sync_with_stdio(false);
    12     cin.tie(0);cout.tie(0);
    13     string s;
    14     int cnt=1,maxx=0;
    15     cin>>s;
    16     for(int i=0;i<s.size();++i) {
    17          if(s[i]=='(') {
    18              q.push(i);
    19          }
    20          else if(!q.empty()) {
    21              int u=q.top();
    22              q.pop();
    23              dp[i]=dp[u-1]+i-u+1;
    24              if(dp[i]>maxx) {
    25                  maxx=dp[i];
    26                  cnt=1;
    27              }
    28              else if(dp[i]==maxx) {
    29                  cnt++;
    30              }
    31          }
    32     }
    33     if(maxx==0) cout<<0<<" "<<1;
    34     else cout<<maxx<<" "<<cnt;
    35     return  0;
    36 }
    View Code

    解题思路2:先找出能够括号匹配的子串,然后判断哪个最长。具体做法是分别从前向后和从后向前遍历一遍,比如从前向后遍历的时候,遇到一个右括号且左括号不为0的时候,说明这个右括号是肯定可以括号匹配的,记录下来dp[i]=1,反向遍历也是同样操作。

    然后for循环遍历记录数组,看dp[i]是否为1,找出最长的及其个数,代码比文字更好理解。

    附ac代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <stack>
     6 using namespace std;
     7 const int maxn = 1e6+5;
     8 int dp[maxn];
     9 stack<int>q;
    10 int main() {
    11     ios::sync_with_stdio(false);
    12     cin.tie(0);cout.tie(0);
    13     string s;
    14     int cnt=0,maxx=0,ans=0;
    15     cin>>s;
    16     for(int i=0;i<s.size();++i) {
    17         if(s[i]=='(') {
    18             ++cnt;
    19         }
    20         else if(cnt>0) {
    21             dp[i]=1;
    22             --cnt;
    23         }
    24     }
    25     cnt=0;
    26     for(int i=s.size()-1;i>=0;--i) {
    27         if(s[i]==')') {
    28             ++cnt;
    29         }
    30         else if(cnt>0) {
    31             dp[i]=1;
    32             --cnt;
    33         }
    34     }
    35     cnt=1;ans=1;
    36     for(int i=0;i<s.size();++i) {
    37         if(dp[i]&&dp[i+1]) {
    38             ++cnt;
    39         }
    40         else cnt=1;
    41         if(cnt>maxx) {
    42             maxx=cnt;
    43             ans=0;
    44         }
    45         if(cnt==maxx) {
    46             ++ans;
    47         }
    48     }
    49     if(maxx==1) cout<<0<<" "<<1;
    50     else cout<<maxx<<" "<<ans;
    51     return  0;
    52 }
    View Code
  • 相关阅读:
    正则表达式:(?=a)是什么意思?
    炫酷的 CSS 形状(值得收藏)
    右边菜单侧拉框
    iframe的父子层跨域 用了百度的postMessage()方法
    二级联动菜单
    一个类似职位选择的二级多选
    iOS sharedk短信分享
    Xcode6新建项目没有.pch
    iOS An error was encountered while running (Domain = FBSOpenApplicationErrorDomain, Code = 4)
    转 UINavigationController标题文字颜色
  • 原文地址:https://www.cnblogs.com/zmin/p/7696259.html
Copyright © 2020-2023  润新知