837B. Balanced Substring

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a string s consisting only of characters 0 and 1. A substring [l, r] of s is a string slsl + 1sl + 2... sr, and its length equals to r - l + 1. A substring is called balanced if the number of zeroes (0) equals to the number of ones in this substring.

You have to determine the length of the longest balanced substring of s.

Input
The first line contains n (1 ≤ n ≤ 100000) — the number of characters in s.

The second line contains a string s consisting of exactly n characters. Only characters 0 and 1 can appear in s.

Output
If there is no non-empty balanced substring in s, print 0. Otherwise, print the length of the longest balanced substring.

Examples
inputCopy
8
11010111
outputCopy
4
inputCopy
3
111
outputCopy
0
Note
In the first example you can choose the substring [3, 6]. It is balanced, and its length is 4. Choosing the substring [2, 5] is also possible.

In the second example it's impossible to find a non-empty balanced substring.

题目就是要你找出最长的0的数量和1的数量相等的长度是多少

唉,一开始觉得2分能做,还做了半天,后面发现有问题有找不出答案,后面一看结果太简单了

把0当成-1,建一个结构体,存前缀和,并保持当前的位置的序号,然后sort,前缀和相同的位置序号相减,保留最大值就好了,第0个为0,0,否则有问题

#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<stdio.h>
#include<float.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define sf scanf
#define pf printf
#define fi first
#define se second
#define mp make_pair
#define pii pair<int,int>
#define scf(x) scanf("%d",&x)
#define prf(x) printf("%d\n",x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define mm(x,b) memset((x),(b),sizeof(x))
#define scfff(x,y,z) scanf("%d%d%d",&x,&y,&z)
typedef long long ll;
const ll mod=1e9+7;
using namespace std;

const double eps=1e-8;
const int inf=0x3f3f3f3f;
const double pi=acos(-1.0);
const int N=2e5+10;
char a[N];
struct node{
    int num;
    int pos;
}q[N];
bool cmp(node x,node y)
{
    if(x.num == y.num ) return x.pos < y.pos ;
    return x.num <y.num ;
 } 
int main()
{
    int n;scf(n);
    sf("%s",a+1);
    
    rep(i,0,n+1)
    {
        if(i==0)
        {
            q[i].num = 0;
            q[i].pos= 0;
        }else
        {
            if(a[i]=='1')
            {
                q[i].num = q[i-1].num +1;
            }else
            {
                q[i].num = q[i-1].num -1;
            }
            q[i].pos=i;
        }
    }
    sort(q,q+n+1,cmp);
    int ans=0;
    rep(i,1,n+1)
    {
        if(q[i].num == q[i-1].num )
        {
            int j=i;
            while(q[j].num ==q[i-1].num&&j<=n) j++;
            j--;
            ans=max(ans,q[j].pos -q[i-1].pos);
            i=j;
        }
    }
    prf(ans);
    return 0;
}

转载于:https://www.cnblogs.com/wzl19981116/p/10752796.html

<think>我们要移除字符串中的左右两边的括号,但要注意只移除最外层的括号,而不是字符串内部可能存在的括号。例如,输入字符串:"(gALL_nCLKS_nPTA4)",我们希望得到:"gALL_nCLKS_nPTA4"但是,我们也要考虑一些边界情况:1.字符串可能没有括号,例如:"gALL_nCLKS_nPTA4"2.字符串可能只有左括号或右括号,例如:"(gALL_nCLKS_nPTA4"或"gALL_nCLKS_nPTA4)"3.字符串可能有多个括号嵌套,但我们只移除最外层的一对括号,例如:"((value))"变成"(value)"4.字符串可能为空字符串思路:我们可以检查字符串的第一个字符和最后一个字符,如果它们分别是'('和')',那么我们就移除这一对括号。但是要注意,如果字符串内部也有括号,我们只移除最外层的一对。然而,我们也要注意,有时候可能最外层只有左括号没有右括号,或者相反。所以我们需要确保同时存在一对匹配的括号在最外层。因此,更安全的做法是:1.检查字符串长度是否至少为2(因为一对括号需要两个字符)2.检查第一个字符是否为'(',最后一个字符是否为')'3.如果满足条件,则移除第一个和最后一个字符但是,这种方法会不会有问题?例如,如果字符串是"()()",我们移除外层括号会变成")(",这显然不是我们想要的。但是题目要求是移除最外层的括号,那么对于"()()"这样的字符串,最外层并没有一对括号包裹整个字符串,所以不应该移除。所以我们的目标实际上是:当整个字符串被一对括号包裹(即开头是'(',结尾是')')时,移除这一对括号。因此,我们只移除最外层的一对括号,而不考虑内部结构。但是,如果字符串是"((a))",我们希望移除最外层的一对括号,变成"(a)"。按照上述方法,我们只移除一次,所以是可行的。所以代码可以这样写:方法一:使用条件判断和字符串切片方法二:使用正则表达式(但要注意正则表达式可能无法处理嵌套,不过我们只处理最外层,所以可以用)这里给出两种方法。方法一:条件判断步骤:-如果字符串长度小于2,直接返回原字符串(因为不可能有一对括号)-如果第一个字符是'('且最后一个字符是')',则返回子字符串(从索引1到倒数第二个)-否则,返回原字符串方法二:正则表达式我们可以使用正则表达式:/^\((.*)\)$/来匹配整个字符串,然后替换为捕获的内容。但是要注意,这个正则表达式会匹配整个字符串被括号包裹的情况,并且捕获括号内的内容。但是,如果字符串内部有括号,这个正则表达式仍然会匹配最外层的括号,因为正则表达式是贪婪匹配。但是,这个方法有一个问题:如果字符串是")(",那么它不会被匹配,因为开头是')',结尾是'(',不符合。所以正则表达式是安全的。但是,我们需要注意,正则表达式匹配整个字符串,所以如果字符串中有换行符,我们需要使用`/^\((.*)\)$/s`(s标志使.匹配换行符),但通常我们的字符串没有换行符。我们这里不使用正则表达式,因为条件判断更简单直接。代码实现:我们写一个函数,名为removeOuterParentheses,输入一个字符串,返回移除最外层括号后的字符串。考虑各种情况:-空字符串:返回空字符串-长度不足2:返回原字符串-开头和结尾是括号:移除-其他情况:返回原字符串但是,我们只移除一次,因为我们只关心最外层的一对。测试用例:1.removeOuterParentheses('(gALL_nCLKS_nPTA4)')->'gALL_nCLKS_nPTA4'2.removeOuterParentheses('(gALL_nCLKS_nPTA4')->'(gALL_nCLKS_nPTA4'//缺少右括号3.removeOuterParentheses('gALL_nCLKS_nPTA4)')->'gALL_nCLKS_nPTA4)'//缺少左括号4.removeOuterParentheses('((gALL_nCLKS_nPTA4))')->'(gALL_nCLKS_nPTA4)'//两层括号,移除最外层5.removeOuterParentheses('')->''6.removeOuterParentheses('a')->'a'7.removeOuterParentheses('()')->''//移除后为空8.removeOuterParentheses('()()')->'()()'//不会被移除,因为整个字符串没有被一对括号包裹注意:第8个例子,整个字符串是"()()",第一个字符是'(',但最后一个字符是')',所以满足条件?但是这样移除后变成")(",这显然不对。所以我们需要明确:我们只移除当整个字符串被一对括号包裹的情况,即字符串的开头和结尾是一对匹配的括号,并且这对括号是最外层的。但是,对于"()()",整个字符串并不是被一对括号包裹,而是由两个独立的括号对组成。所以我们的方法一(检查首尾)会错误地移除首尾括号,因为:首字符:'(',尾字符:')',然后移除,得到")("。因此,我们需要重新考虑:我们的目标字符串可能是什么结构?实际上,题目要求移除最外层的括号,这个要求通常出现在解析嵌套结构时,比如解析类似括号表达式。但题目中给出的例子只有一个括号对。根据问题描述,我们只处理一个括号对包裹整个字符串的情况。所以对于"()()",它并不是整个字符串被一个括号对包裹,而是两个括号对并列。所以,我们的函数应该只处理整个字符串被一个括号对包裹的情况,而不管内部结构。那么对于"()()",它首尾也是括号,但移除后得到")(",这不符合我们的预期吗?实际上,如果输入是"()()",那么最外层并没有一个括号包裹整个字符串,所以我们不应该移除。但是按照条件判断,我们只检查首尾,所以会移除。所以,我们需要更严格的条件:只有当整个字符串被一对括号包裹,并且这对括号是匹配的(在嵌套结构中,我们不考虑嵌套匹配,只考虑位置)?但是我们的条件已经很简单了。实际上,我们只根据位置,不根据匹配性(因为匹配性需要扫描整个字符串,而我们不想这么做)。所以,我们只能移除首尾的括号,不管内部结构。那么,对于"()()",我们移除首尾括号后得到")(",这可能是用户不希望的。但是,问题描述是“移除左右两边的括号”,所以这个函数的行为就是移除首尾的括号(如果首是'('且尾是')')。所以,我们需要明确需求:如果需求就是移除首尾的括号(不管内部结构),那么我们就这么做。但是,题目中的例子只有一个括号对,所以移除首尾的括号即可。所以,我们按照简单的方法实现。但是,如果需求是移除最外层的括号,且要保证括号匹配,那么我们需要用栈来检查整个字符串的括号匹配,然后移除最外层的匹配括号。这比较复杂,而且题目没有要求。根据问题描述,我们只移除左右两边的括号,所以我们就移除首尾的括号(如果存在)。因此,我们按照方法一实现。但是,为了安全,我们可以考虑:如果字符串开头是'(',结尾是')',我们就移除。否则就不移除。代码:我们写一个函数:</think>以下是一个完整的 JavaScript 解决方案,用于移除字符串两端的括号,包含多种实现方法和边界情况处理: ```javascript /** * 移除字符串两端的括号(如果存在) * @param {string} str - 输入字符串 * @returns {string} 移除括号后的字符串 */ function removeOuterParentheses(str) { // 方法1: 使用正则表达式(简洁高效) const regexRemove = (s) => { // 使用正则匹配字符串开头和结尾的括号 return s.replace(/^\(|\)$/g, ''); }; // 方法2: 条件判断和切片(直观易懂) const conditionalRemove = (s) => { if (s.length < 2) return s; let start = 0; let end = s.length; // 检查并移除开头的 '(' if (s.startsWith('(')) { start = 1; } // 检查并移除结尾的 ')' if (s.endsWith(')')) { end = s.length - 1; } return s.substring(start, end); }; // 方法3: 使用数组操作(函数式编程) const arrayRemove = (s) => { const chars = [...s]; // 移除开头的 '(' if (chars[0] === '(') { chars.shift(); } // 移除结尾的 ')' if (chars[chars.length - 1] === ')') { chars.pop(); } return chars.join(''); }; // 根据输入长度选择最佳方法 if (str.length > 1000) { // 大字符串使用正则表达式(性能最佳) return regexRemove(str); } else { // 小字符串使用条件判断(更直观) return conditionalRemove(str); } } // 测试用例 const testCases = [ { input: "(gALL_nCLKS_nPTA4)", expected: "gALL_nCLKS_nPTA4" }, { input: "((nested))", expected: "(nested)" }, { input: "(onlyLeft)", expected: "onlyLeft" }, { input: "onlyRight)", expected: "onlyRight" }, { input: "noParentheses", expected: "noParentheses" }, { input: "()", expected: "" }, { input: ")", expected: "" }, { input: "(", expected: "" }, { input: "", expected: "" }, { input: "(mixed(case)_with)inner)", expected: "mixed(case)_with)inner" }, { input: " (spaces) ", expected: " spaces " }, ]; // 执行测试 console.log("测试结果:"); testCases.forEach((test, index) => { const result = removeOuterParentheses(test.input); const status = result === test.expected ? "✓ 通过" : "✗ 失败"; console.log(`${index + 1}. 输入: "${test.input}"`); console.log(` 期望: "${test.expected}"`); console.log(` 实际: "${result}"`); console.log(` 状态: ${status}`); console.log("---"); }); // 高级功能:移除多层外层括号 function removeMultiLayerParentheses(str) { let result = str; let changed = true; // 循环移除外层括号直到不再变化 while (changed) { const newResult = removeOuterParentheses(result); changed = newResult !== result; result = newResult; } return result; } console.log("\n多层括号移除测试:"); console.log('输入: "((multi))" =>', removeMultiLayerParentheses("((multi))")); console.log('输入: "(((three)))" =>', removeMultiLayerParentheses("(((three)))")); // 高级功能:选择性移除括号(保留内部括号) function removeOuterParenthesesSelectively(str, preserveInner = true) { if (str.length < 2) return str; let start = 0; let end = str.length; // 检查并移除开头的 '(' if (str[0] === '(') { start = 1; } // 检查并移除结尾的 ')' if (str[str.length - 1] === ')') { end = str.length - 1; } const result = str.substring(start, end); // 如果不需要保留内部括号,递归处理 if (!preserveInner) { return removeOuterParenthesesSelectively(result, false); } return result; } console.log("\n选择性移除测试:"); console.log('保留内部: "((a)(b))" =>', removeOuterParenthesesSelectively("((a)(b))")); console.log('不保留内部: "((a)(b))" =>', removeOuterParenthesesSelectively("((a)(b))", false)); // 实用工具:创建括号移除函数(带配置) function createParenthesisRemover(config = {}) { const { removeLeft = true, removeRight = true, recursive = false, onlyIfBalanced = false } = config; return function(str) { // 检查是否只处理平衡括号 if (onlyIfBalanced) { const balanced = isBalancedParentheses(str); if (!balanced) return str; } let start = 0; let end = str.length; if (removeLeft && str.startsWith('(')) { start = 1; } if (removeRight && str.endsWith(')')) { end = str.length - 1; } const result = str.substring(start, end); // 递归处理 if (recursive) { return createParenthesisRemover(config)(result); } return result; }; } // 辅助函数:检查括号是否平衡 function isBalancedParentheses(str) { let count = 0; for (let i = 0; i < str.length; i++) { if (str[i] === '(') { count++; } else if (str[i] === ')') { count--; if (count < 0) return false; // 出现多余的右括号 } } return count === 0; // 平衡时计数应为0 } // 使用工厂函数创建自定义移除器 console.log("\n自定义括号移除器:"); const removeOnlyLeft = createParenthesisRemover({ removeRight: false }); console.log('仅移除左侧: "(left)right)" =>', removeOnlyLeft("(left)right)")); const balancedRemover = createParenthesisRemover({ onlyIfBalanced: true }); console.log('平衡检查: "(unbalanced" =>', balancedRemover("(unbalanced")); console.log('平衡检查: "(balanced)" =>', balancedRemover("(balanced)")); // 性能测试:处理大字符串 function generateLargeString(size, pattern = "(text)") { return pattern.repeat(size); } console.log("\n性能测试:"); const largeString = generateLargeString(10000); // 10K字符 console.time("移除大字符串括号"); const result = removeOuterParentheses(largeString); console.timeEnd("移除大字符串括号"); console.log("结果长度:", result.length); // 处理特殊括号类型 function removeAllParenthesesTypes(str) { const parenthesisPairs = [ { left: '(', right: ')' }, { left: '[', right: ']' }, { left: '{', right: '}' }, { left: '<', right: '>' } ]; let result = str; for (const pair of parenthesisPairs) { if (result.startsWith(pair.left) && result.endsWith(pair.right)) { result = result.substring(1, result.length - 1); } } return result; } console.log("\n处理多种括号类型:"); console.log('输入: "{value}" =>', removeAllParenthesesTypes("{value}")); console.log('输入: "[array]" =>', removeAllParenthesesTypes("[array]")); ``` ### 代码详细解释: #### 1. 核心方法:`removeOuterParentheses` ```javascript function removeOuterParentheses(str) { if (str.length < 2) return str; let start = 0; let end = str.length; if (str.startsWith('(')) { start = 1; } if (str.endsWith(')')) { end = str.length - 1; } return str.substring(start, end); } ``` - **边界处理**:检查字符串长度,避免无效操作 - **开头检查**:使用 `startsWith` 检测开头的 '(' - **结尾检查**:使用 `endsWith` 检测结尾的 ')' - **切片操作**:使用 `substring` 提取中间部分 #### 2. 多层括号移除 ```javascript function removeMultiLayerParentheses(str) { let result = str; let changed = true; while (changed) { const newResult = removeOuterParentheses(result); changed = newResult !== result; result = newResult; } return result; } ``` - 循环应用移除函数 - 检测每次操作后字符串是否变化 - 适用于处理 `((多层))` 的情况 #### 3. 括号平衡检查 ```javascript function isBalancedParentheses(str) { let count = 0; for (let i = 0; i < str.length; i++) { if (str[i] === '(') count++; else if (str[i] === ')') { count--; if (count < 0) return false; // 多余的右括号 } } return count === 0; // 左右括号数量相等 } ``` - 遍历字符串统计括号数量 - 遇到左括号计数增加,右括号计数减少 - 计数为负表示不平衡 - 最终计数应为零才平衡 #### 4. 可配置的移除工厂 ```javascript function createParenthesisRemover(config = {}) { return function(str) { // 根据配置处理字符串 }; } ``` - **配置选项**: - `removeLeft`:是否移除左侧括号 - `removeRight`:是否移除右侧括号 - `recursive`:是否递归移除多层 - `onlyIfBalanced`:仅当括号平衡时移除 - 返回一个专门处理括号的定制函数 #### 5. 多种括号类型支持 ```javascript function removeAllParenthesesTypes(str) { const parenthesisPairs = [ { left: '(', right: ')' }, { left: '[', right: ']' }, { left: '{', right: '}' }, { left: '<', right: '>' } ]; // 检查并移除各种括号 } ``` - 支持常见括号类型:圆括号、方括号、花括号、尖括号 - 遍历所有括号类型对 - 按顺序处理每种括号的移除 ### 边界情况处理: 1. **空字符串**: ```javascript removeOuterParentheses(""); // 返回 "" ``` 2. **单字符字符串**: ```javascript removeOuterParentheses(")"); // 返回 "" removeOuterParentheses("("); // 返回 "" removeOuterParentheses("a"); // 返回 "a" ``` 3. **只有括号**: ```javascript removeOuterParentheses("()"); // 返回 "" ``` 4. **不平衡括号**: ```javascript removeOuterParentheses("(unbalanced"); // 返回 "unbalanced" removeOuterParentheses("unbalanced)"); // 返回 "unbalanced" ``` 5. **空格处理**: ```javascript removeOuterParentheses(" (text) "); // 返回 " text " ``` 6. **混合括号**: ```javascript removeOuterParentheses("(text]"); // 返回 "text]" ``` ### 性能优化: 1. **大字符串处理**: ```javascript // 使用正则表达式处理大字符串 function efficientRemove(str) { return str.replace(/^\(|\)$/g, ''); } ``` - 正则表达式在引擎层面优化,处理大字符串更快 - 避免创建中间字符串 2. **内存优化**: ```javascript function memoryEfficientRemove(str) { if (str.length === 0) return ""; let start = 0; let end = str.length; if (str.charCodeAt(0) === 40) { // '(' 的 ASCII 码 start = 1; } if (str.charCodeAt(str.length - 1) === 41) { // ')' 的 ASCII 码 end = str.length - 1; } return str.substring(start, end); } ``` - 使用 `charCodeAt` 替代字符串比较 - 避免创建新数组或中间对象 3. **流式处理**: ```javascript function* streamParenthesisRemover(inputStream) { for await (const chunk of inputStream) { const processed = removeOuterParentheses(chunk); yield processed; } } ``` - 适用于处理文件或网络流 - 分块处理避免内存溢出 ### 实际应用场景: 1. **数据清洗**: ```javascript // 清洗API响应中的括号 const apiResponse = '({"id": 123, "name": "John"})'; const cleaned = removeOuterParentheses(apiResponse); const data = JSON.parse(cleaned); ``` 2. **配置文件处理**: ```javascript // 处理配置文件中的值 const config = { port: '(8080)', host: '(localhost)' }; const cleanConfig = Object.fromEntries( Object.entries(config).map(([key, value]) => [key, removeOuterParentheses(value)] ) ); ``` 3. **用户输入清理**: ```javascript // 清理表单输入 document.getElementById('submit').addEventListener('click', () => { const userInput = document.getElementById('input').value; const cleanedInput = removeOuterParentheses(userInput); // 使用清理后的输入 }); ``` 4. **SQL查询参数处理**: ```javascript // 处理SQL查询中的参数 const query = "SELECT * FROM users WHERE name = ?"; const params = ['(John)']; const cleanParams = params.map(param => removeOuterParentheses(param) ); db.query(query, cleanParams, (err, result) => { // 处理结果 }); ``` ### 最佳实践: 1. **防御性编程**: ```javascript function safeRemoveParentheses(str) { if (typeof str !== 'string') { console.warn('输入必须是字符串'); return str; } // 实际移除逻辑 } ``` 2. **单元测试**: ```javascript // 使用Jest进行单元测试 test('移除括号函数', () => { expect(removeOuterParentheses('(test)')).toBe('test'); expect(removeOuterParentheses('(onlyLeft')).toBe('onlyLeft'); expect(removeOuterParentheses('')).toBe(''); expect(removeOuterParentheses(null)).toBe(null); }); ``` 3. **国际化考虑**: ```javascript // 支持全角括号 function internationalRemove(str) { return str .replace(/^\(|(|\)|)$/g, '') .replace(/^\)|)|\(|($/g, ''); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值