2019届牛客网暑期多校赛第三场B题

链接:https://ac.nowcoder.com/acm/contest/883/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
ZYB loves binary strings (strings that only contains 0' and1’). And he loves equal binary strings\textit{equal binary strings}equal binary strings more, where the number of 0' and the number of1’ in the string are equal.

ZYB wants to choose a substring from an original string T\ T T so that it is an equal binary string\textit{equal binary string}equal binary string with the longest length possible. He also wants to choose a subsequence of T\ T T which meets the same requirements.

A string v\ v v is a substring of a string w\ w w if v\ v v is empty, or there are two integers l\ l l and r (1≤l≤r≤∣w∣)r \ (1 \le l \le r \le |w|)r (1≤l≤r≤∣w∣) such that v=wlwl+1⋯wrv=w_lw_{l+1}\cdots w_rv=wl​wl+1​⋯wr​. A string v\ v v is a subsequence of a string w\ w w if it can be derived from w\ w w by deleting any number (including zero) of characters without changing the order of the remaining characters.

For simplicity, you only need to output the maximum possible length. Note that the empty string is both a substring and a subsequence of any string.
输入描述:

The first line of the input contains a single integer N (1≤N≤100000)N \ (1 \le N \leq 100000)N (1≤N≤100000), the length of the original string T\ T T. The second line contains a binary string with exactly N\ N N characters, the original string T\ T T.

输出描述:

Print two integers A\ A A and B\ B B, denoting the answer for substring and subsequence respectively.

示例1
输入

8
01001001

输出

4 6

题意:
给出一个长度为n的仅包含0和1的字符串,让你找一个子串,子串中0和1的个数相等,让这个子串尽可能长,输出这个长度,另外再找一个子序列,子序列中0和1的个数相等,并且尽可能让子序列长,输出这个长度。

题解:
子串是针对连续的部分,子序列是针对不一定连续的部分,比如字符串ABCDEF,子串有ABC,ABCD,BCDE,而子序列可以有ACF,字符不要求连续,但要求按原字符串中的顺序出现,所以这题求子序列的长度就是找出原字符串中0和1的数目ans0,ans1,然后长度就是min(ans0,ans1)*2,子序列长度比较容易,但子串长度就比较麻烦了。

分析字符串特征,求0和1的数目关系,我们就可以标记在位置i时0和1的数量关系,那么可以知道,如果位置i和位置j的0和1数量关系一样,并且i<j,那么在区间i+1到j形成的子串一定是0和1数目相等的子串,比如样例 01001001,位置1:num0=1,num1=0->num0-num1=1,位置5:num0=3,num1=2->num0-num1=1,0和1的数量关系相等,所以2到5之间的0和1数目相等,所以这里得到一个满足题目要求的子串长度5-1=4。

最后处理:由上面的分析我们已经知道了这个关系,那么我们就需要标记每个位置0和1的数量关系,这里我用数组now表示,now[i]表示在位置i时0和1的数量关系,如果now[i]=now[j],i<j,就能得到一个满足题目要求的子串长度j-i,而在循环遍历时,为了方便知道在位置i时,哪个位置的数量关系和i的一样,我这里定义了一个数组pre,表示这个数量关系最早出现的位置,也就是pre[N+now[i]]=i,这里N=1e5,因为now[i]可能为负数,所以得加N,那么在循环遍历时,我就只需要mx=max(mx,i-pre[N+now[i]]),就可以得到答案,但这里得注意一下,就是pre[N]=0,因为在位置0,0和1的数量也是相等的都为0;

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1000;
string s;
int now[N],pre[2*N];
int main()
{
    int n;
    cin>>n>>s;
    memset(now,0,sizeof(now));
    memset(pre,-1,sizeof(pre));
    int ans0=0,ans1=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='0')
        	ans0++;
        else 
        	ans1++;
        	//字符串下标从0开始,但是我这里数组下标为方便运算从1开始,所以i+1
		now[i+1]=ans1-ans0;    
    }
	pre[N]=0;
    for(int i=1;i<=n;i++)
    {
    	//找每种数量关系最开始出现的位置
    	if(pre[N+now[i]]==-1)
    	pre[N+now[i]]=i;
	}
    int mx=0;
    for(int i=1;i<=n;i++)
    	mx=max(mx,i-pre[N+now[i]]);
    cout<<mx<<" "<<min(ans0,ans1)*2<<endl;
    return 0;  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值