[LeetCode 32] 最长有效括号
作者:互联网
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
没睡醒的脑回路:转换成 +1,-1 序列,利用两个充要条件(子段和为 0,子段任意前缀的和非负),在前缀和序列上用二分找满足条件的最远点
class Solution {
public:
int longestValidParentheses(string s) {
// 对前缀和序列 a,假设 s[i]='('
// 令 j 为 i 右侧 a[i]-2 首次出现位置(不存在则为 n)
// 则任意 i<k<j 满足 a[k]=a[i]-1 的 k 都是合法的右端点,贡献 k-i+1
int n=s.length();
if(n==0) return 0;
vector<int> a(n);
a[0]=s[0]=='('?1:-1;
for(int i=1;i<n;i++) if(s[i]=='(') a[i]=a[i-1]+1; else a[i]=a[i-1]-1;
vector<vector<int>> o(n+n+2,vector<int>(1,-1));
for(int i=0;i<n;i++) o[a[i]+n+1].push_back(i);
for(int i=0;i<n+n+2;i++) o[i].push_back(n);
int ans=0;
for(int i=0;i<n;i++)
{
if(s[i]!='(') continue;
int start=i,stop;
if(a[i]-2+n+1<0) stop=n;
else stop=*lower_bound(o[a[i]-2+n+1].begin(),o[a[i]-2+n+1].end(),start);
auto ptr=lower_bound(o[a[i]-1+n+1].begin(),o[a[i]-1+n+1].end(),stop);
if(ptr==o[a[i]-1+n+1].begin()) continue;
--ptr;
if(ptr==o[a[i]-1+n+1].end()) continue;
int end=*ptr;
if(end==n) continue;
ans=max(ans,end-start+1);
}
return ans;
}
};
注意到删除任意前缀后,无法匹配的括号仍然无法匹配。用栈模拟并标记所有可以匹配的括号后,求最长连续全 1 段即可
标签:匹配,前缀,子段,int,32,括号,序列,LeetCode 来源: https://www.cnblogs.com/mollnn/p/15812384.html