题目链接:
题目大意:
给出一个括号的序列,求最长的合法的子序列。
题目分析:
- 定义dp[i]表示第i个位置的右括号结尾的合法序列的左边界
- 定义lef[i]表示第i个位置的右括号匹配到的左括号的位置
- 利用栈进行模拟,可以得到lef[i],dp[i]的转移方程如下:
dp[i]=dp[lef[i]−1](s[lef[i]−1]==′)′)
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <algorithm>
#define MAX 1000007
using namespace std;
char s[MAX];
int b[MAX];
int dp[MAX];
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() )
{
b[i] = -1;
dp[i] = -1;
continue;
}
int x = stk.top();
stk.pop();
dp[i] = b[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" );
}
}