codeforces 5C
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.
The first line of the input file contains a non-empty string, consisting of «(» and «)» characters. Its length does not exceed 106.
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".
)((())))(()())
6 2
))(
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 }
解题思路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 }