CodeForces - 873 B. Balanced Substring

给定一个只包含0和1的字符串s,找到最长的平衡子串,即子串中0和1的数量相等。输出最长平衡子串的长度。可以通过转化为求0的最长子序列问题来解决,利用哈希映射记录每个子序列和首次出现的位置,当和再次出现时,计算两个位置的差值即为最长平衡子串的长度。
摘要由CSDN通过智能技术生成

B. Balanced Substring

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard 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

input

Copy

8
11010111

output

Copy

4

input

Copy

3
111

output

Copy

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.

题解:

1 . 如果子串中0的个数与1的个数相等的话 就说这个子串平衡求 最长平衡子串的长度

2. 这个问题可以看成求最长子序列问题。把0转化成-1,问题就变成求子序列为0的最长长度。

为了简化代码,可以借用map,因为map不能重复插入相同的数,所以一个数的当前位置就是第一次插入的位置。

 3. 我们对序列连续求和,将和放入一个新数组中(数组大小应该为原来的两倍)。注意如果一个和之前存在过,现在又重复出现,这就说明这两个位置之间的和为零,相减为长度。(爱是一道光,绿得你发慌)

为了方便理解,我模拟一下样例1:字体太丑,不要介意。

代码如下:

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <string>
#include <map>
#define N 100005
using namespace std;
//最长平衡子序列问题 
int main()
{
    int n;
    string s;
    int a[N];
    map<int,int>mp;
    mp.clear();
    cin>>n>>s;
 
    for(int i=0;i<n;i++)
    {
        if(s[i]=='0')
        {
            a[i+1]=-1;
        }else if(s[i]=='1'){
            a[i+1]=1;
        }
    }//求和为0最长子序列问题
    int sum=0,maxx=0;
    for(int i=1;i<=n;i++)//注意s到a更新数据时,下标+1,从1开始
    {
        sum+=a[i];
        if(mp[sum])
        {
            maxx=max(maxx,i-mp[sum]);
//如果这个和之前存在,现在又出现,说明这个区间子序列满足条件,相减为长度
        }else mp[sum]=i;
//否则将数插入,根据map不能重复插入的特性,其位置为第一次出现位置i。
        if(sum==0)
            maxx=max(maxx,i);//如果前缀和为零,从1到i区间一直满足条件
    }
    cout<<maxx<<endl;
    return 0;
 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值