(CodeForces - 5C)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解决。设f[i]表示位置为i的右括号结尾的最长合法括号子序列的长度,则易得:
f[i]=f[tmp-1]+i-tmp+1,其中tmp表示与位置为i的右括号匹配的左括号的位置(可以用栈记录)。
方法二:贪心。我们从左到右依次扫一遍括号串,碰到左括号cnt++,碰到右括号,并且此时cnt不为0,则说明该右括号有与之匹配的左括号,是合法的,记vis[i]为1;同理再从右到左扫一遍括号,记录合法的左括号,令vis[i]为1。而我们要做的就是统计连续1出现的个数的最大值,这只要从左到右扫一遍即可,所以该算法是O(n)的。
栈+dp实现代码:
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn=1000005;
char s[maxn];
int f[maxn];
stack<int> st;
int main()
{
scanf("%s",s+1);
int ans=0,sum=0;
int len=strlen(s+1);
memset(f,0,sizeof(f));
for(int i=1;i<=len;i++)
{
if(s[i]=='(') st.push(i);
else
{
if(!st.empty())
{
int t=st.top();
st.pop();
f[i]=f[t-1]+i-t+1;
if(ans<f[i]) ans=f[i],sum=1;
else if(ans==f[i]) sum++;
}
}
}
if(ans==0) sum=1;
printf("%d %d\n",ans,sum);
return 0;
}
贪心实现代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000005;
char s[maxn];
bool vis[maxn];
int main()
{
scanf("%s",s);
int len=strlen(s);
int cnt=0;
memset(vis,false,sizeof(vis));
for(int i=0;i<len;i++)
{
if(s[i]=='(') cnt++;
if(s[i]==')')
{
if(cnt)
{
vis[i]=true;
cnt--;
}
}
}
cnt=0;
for(int i=len-1;i>=0;i--)
{
if(s[i]==')') cnt++;
if(s[i]=='(')
{
if(cnt)
{
vis[i]=true;
cnt--;
}
}
}
int ans=0,sum=0;//ans表示最长匹配括号串的括号个数,sum表示最长匹配括号串一共有几个
cnt=0;
for(int i=0;i<len;i++)
{
if(vis[i]) cnt++;
else cnt=0;
if(ans<cnt) ans=cnt,sum=1;
else if(ans==cnt) sum++;
}
if(ans==0) sum=1;//没找到匹配括号串,则按题目要求给sum赋值1
printf("%d %d\n",ans,sum);
return 0;
}