codeforces 5c dp

题意:给一串括号序列,求出最长的合法序列的长度以及个数

思路:先求出长度,然后再用相同的办法统计出个数

定义dp[i]表示第i个位置的右括号结尾的合法序列的左边界

定义lef[i]表示第i个位置的右括号匹配到的左括号的位置

转移方程如下:

dp[i]=dp[lef[i]−1](s[lef[i]−1]==′)′)

#include <bits/stdc++.h> 
using namespace std;

const int maxn = 1000007;
char s[maxn];
int lef[maxn];
int dp[maxn];
stack <int> stk;

void Clear(){
    while(! stk. empty())
        stk. pop();
}
int main(){
    while(~ scanf("%s", s)){
        Clear();
        int n = strlen(s);
        for(int i = 0; i < n; i ++){
            if(s[i] == '(')
                stk. push(i);
            if(s[i] == ')'){
                if(stk. empty()){
                    lef[i] = -1;
                    dp[i] = -1;
                    continue;
                }
                int x = stk. top();
                stk. pop();
                dp[i] = lef[i] = x;
                if(s[x - 1] == ')' && dp[x - 1] != -1) 
                    dp[i] = dp[x - 1];
            }
        }
        int ans = 0, num = 0;
        for(int i = 0; i < n; i ++)
            if(s[i] == ')' && dp[i] != -1)
                ans = max(ans, i - dp[i] + 1);
        for (int i = 0; i < n; i ++ )
            if (s[i] == ')' && dp[i] != -1)
                if(i - dp[i] + 1 == ans) 
					num ++;
        if (ans)
            printf("%d %d\n", ans, num);
        else 
			puts("0 1");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/86505349