最长合法括号序列

Description
如果一个括号序列插入"+"和"1"后,可以得到一个正确的数学表达式,那么它被称为"合法"的。例如,序列"(())(
)","()"和"(()(()))"是合法的,但")(","(()"和"(()))("不是合法的。 给出一个由"("和")"字符组成的字符串
。你要找出它最长的是合法括号序列的子串,也同样要找出最长子串的个数。100%的数据:读入的字符串长度小于
等于10^6
Input
Output
Sample Input
)()()(
Sample Output
4 1

sol:栈+dp
f[i]表示到位置i能够形成的最长合法括号序列的子串的长度。
依次处理读入的字符串序列,如果字符为“(”,进栈,如果是“)”,则与栈顶的左括号配对。
如i为正在处理右括号,栈顶为k(k>0),则f[i]=f[k-1]+i-k+1.
最后扫一遍,求出所有能形成的最大子串长度及个数。

代码如下:

#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;
 
const int N=1000005;
 
int n,tot;
int f[N],Q[N];
char s[N];
 
void init()
{int i;
 scanf("%s",s+1);//下标从1开始 
 n=strlen(s+1);
}
 
void dp()
{int i,k; 
 tot=0;//记录栈中元素个数 
 for (i=1;i<=n;i++)
   if (s[i]=='(')//是左小括号 
     Q[++tot]=i;
   else
     if (tot>0)
       {k=Q[tot];//该")"与位置k的"("匹配 
        tot--;
        f[i]=f[k-1]+i-k+1;//f[i]表示到位置i能够形成的最长合法括号序列的子串的长度 
       }
}
 
void out()
{int i,ans=0, cnt=1;
 for (i=1;i<=n;i++) 
   {if (f[i]==ans) 
      cnt++;
    if (f[i]>ans) 
      {ans=f[i];
       cnt=1;
      }
   }
 if (ans==0) cnt=1;
 printf("%d %d
",ans,cnt);
}
 
int main()
{
 init();
 dp();
 out();
 return 0;
}

 

原文地址:https://www.cnblogs.com/cutepota/p/13453749.html