题目
题解思路
y总提供了一种画图来方便理解的方法。
( + 1
) - 1
两个相同高度的点直接如果没有比他们更小的点,那么这段区间就是合法的。
为了方便计算,我们可以将两个点之间的合法括号消除掉,即出栈。
当合法匹配后,我们可以更新答案,此时栈顶的元素,就是与这个点相同高度的点。作差就是此时合法括号的长度。
dp写法 类似与最长上升子序列 ,这里不多说了。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1000100;
char s[N] ;
stack <int> a ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> s ;
int sz = strlen(s) ;
int ans = 0 , cnt = 1 ;
vector <PII> pk ;
for (int i = 0 ; i < sz ; i++ )
{
if ( a.size() && s[i] == ')' && s[a.top()] == '(' )
a.pop();
else
a.push(i);
int r = 0 ;
if ( a.size() )
r = i - a.top() ;
else
r = i + 1 ;
if ( r > ans )
ans = r , cnt = 1 ;
else if ( r == ans && r > 0 )
cnt++ ;
}
cout << ans << " " << cnt << "\n" ;
return 0 ;
}
dp写法
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1000100;
char s[N] ;
stack <int> a ;
int dp[N] ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> s + 1 ;
int sz = strlen(s+1) ;
int ans = 0 , cnt = 1 ;
for (int i = 1 ; i <= sz ; i++ )
{
if ( s[i] == '(' )
{
a.push(i) ;
}else
{
if ( a.size() )
{
int t1 = a.top();
a.pop();
dp[i] = dp[t1-1] + i - t1 + 1 ;
if ( ans == dp[i] )
cnt++;
else if ( ans < dp[i] )
ans = dp[i] , cnt = 1 ;
}
}
}
cout << ans << " " << cnt << "\n" ;
return 0 ;
}