• [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 段即可

  • 相关阅读:
    C#中将全部代码一次性折叠
    C#中图片单击旋转事件
    块参照重命名
    补强圈设计
    c# winform 按名称取得控件
    获得某控件的父控件(容器)中的所有控件
    回车键当Tab键使用
    替换CAD中原有命令为开发人员自己开发的命令的方法
    窗体设置
    判断控件的tag是否为空的方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/15812384.html
Copyright © 2020-2023  润新知