2019牛客暑期多校训练营(第三场) B题

Crazy Binary String
在这里插入图片描述
在这里插入图片描述
题意:给你一个长度为n的01字符串,问该字符串中01个数相等的最长子串和子序列分别是多少。

分析:
首先,大家要知道什么是子序列,什么是子串,子序列是不一定是连续的,它可以是原串中任意元素按照相对位置组成的序列,但是子串就不是了,子串一定是连续的,不可分割的按照绝对位置组成的序列。
知道这个概念之后,大家可以明显的看出,子序列这个答案好求,就是暴力一下,看看这个字符串中0,1的个数,谁最小,最后的答案就是这个最小值乘2;
那子串怎么求,这是个难点。仔细观察可以发现,这与01的对数是有一定的关系的,那么不妨就从这个方面入手,我们定义一个int变量dis,如果当前的字符是0,那么dis–,否则dis++,如果这个dis是第一次出现,那么就用一个数组存一下出现当前这个dis 的下标,如果说这个dis不是第一次出现,那么就用当前这个字符的下标减去下标为dis这个数组里面的值。这就是答案。
为什么呢,因为dis定义为出现0,就减一,出现1就加一,那么当其值不是第一次出现的时候,那么肯定就用当前这个下标减去第一次出现这个值的位置了;
这是因为0与1相互抵消才会产生的现象,只有他们出现的次数相等,才会出现抵消的情况。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#include<stack>
#include<map>
typedef long long ll;
using namespace std;
const int N=1e5+100;
char str[N];
map<int ,int >ma;
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int n;
    scanf("%d%s",&n,str+1);
    int dis=0;
    int num_0=0,num_1=0;
    for(int i=1;i<=n;i++){
        if(str[i]=='0')
            num_0++;
        else
            num_1++;
    }
    int ans=0;
    ma[0]=0;
    for(int i=1;i<=n;i++){
        if(str[i]=='0') dis--;
        else dis++;

        if(ma.count(dis)==0)//这个地方一定要注意,不能用!ma[dis],这样是过不了这组数据:2 01
            ma[dis]=i;
        else
        ans=max(ans,i-ma[dis]) ;
    }
    printf("%d %d\n",ans,min(num_0,num_1)*2);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值