题目描述
位于欧洲中部的赫希费尔登狩猎保护区生活着许多动物,雄壮的野牛和凶狠的狼群之间保持着一种平
衡,当野牛的数量和狼群一样多时,它们彼此互不侵犯相安无事,但只要狼的数量多于野牛狼群就会攻
击牛群,而野牛数量占多数时,它们会驱逐狼群到别的地方。
当地的统计学家把牛群和狼群分布通过0和1表示为一个字符串S,S的字串可以表示一个区域内的牛和狼
总数,请你根据这个统计字符串,判断出来这个保护区内能共存最多头野牛和狼的区域,该区域的牛群
和狼群总数是多少。
输入格式
一个字符串,只包含01,长度不超过1000000。
输出格式
一行一个整数,最长的0与1的个数相等的子串的长度。
数据范围
对于10%的数据,字符串长度≤10;
对于100%的数据,字符串长度≤1000000。
样例1
输入
1011
输出
2
样例2
输入
0010100
输出
4
样例3
输入
111
输出
0
题解
本题非常的巧妙,算是以后编程的又一个思路。要找字符串里0,1个数相等的子串,那我们可以把0变成-1,如果相加=0了,那么个数就相等了
。本题非常的巧妙,算是以后编程的又一个思路。要找字符串里0,1个数相等的子串,那我们可以把0变成-1,如果相加=0了,那么个数就相等了。
1.先用前缀和求出前i个数字的和,这样要求任意一个子串的总和就简单了。
2.求完之后,用f[sum[i]]表示前面字符串总和为sum[i]的数字的位置,注意,这里存的是位置,而且一定是最靠前的位置(因为只有第一遍扫到的时候存了),sum[i]是下标,类似于桶排的思想。
3.如果循环到一个f已经被标记过了,那么就算出,他们之间的距离,取max。
4.细节非常重要。
(1)因为可能前面的和是负数,但是下标不能是负数,所以可以给小于0的sum[i]加上一个大数,使它为正。
(2)因为前面的总和也可能是0,所以f要赋-1。
(3)取max时,maxx的初值应该赋成0,因为,如果没有找到就要输出0,当然,这里也可以用一个bool来实现
(4)在刚开始计算前缀和的时候,应该用sum[i+1]=sum[i]-1,这样处理后面的操作比较方便。
代码如下:
#include<bits/stdc++.h>
using namespace std;
string s;
int sum[1000050],f[50000000];
int main()
{
freopen("coexist.in","r",stdin);
freopen("coexist.out","w",stdout);
cin>>s;
for(int i=0;i<s.size();i++)
{
if(s[i]=='0') sum[i+1]=sum[i]-1;
else sum[i+1]=sum[i]+1;
}
memset(f,-1,sizeof(f));
int maxx=0;
f[0]=0;
for(int i=1;i<=s.size();i++)
{
if(sum[i]<0) sum[i]+=2000000;
if(f[sum[i]]==-1) f[sum[i]]=i;
else maxx=max(maxx,i-f[sum[i]]);
}
cout<<maxx;
return 0;
}