51nod 1391 01串

题目链接  https://www.51nod.com/Challenge/Problem.html#!#problemId=1391

发散思维(Why and Zjp tql  %Zjp and Why)

相信每个人看了这道题都会有思路

:从当前位置向左找最大匹配位置,从当前位置从后找最大匹配位置(原谅我太垃圾只能想出o(n^2)的算法)

我们可以把0当成-1,把1当成1,这样求下前缀和,如果当前位置的前缀和大于0说明1 大于0,反之同理

从前往后找当前位置的前缀小于0的话他的长度就是本身,如果大于0的话,我们需要找当前位置前缀和+ 1的地方是否在原来的时候存在过,如果存在当前位置 - 前缀和+ 1的位置就是最大距离(这是为什么那?)

证明:我们都知道前缀和相同的位置中间的和加起来为0,所以我们就找前缀和+1的位置,你可能会疑惑为什么不找前缀和 + 2 ,+ 3的位置,因为前缀和+ 1位置一定比前缀和 + 2的地方先出现 证毕,倒着找也是同样的道理;

 

AC代码如下

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
//typedef __int128 bll;
typedef long double ld;
 
const ll maxn = 1e6 + 5;

char a[maxn];
ll b[maxn],c[maxn],flag[maxn];
int main() 
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
 	
 	cin >> a + 1;
 	ll n = strlen(a + 1);
 	
 	ll cnt = 0;
 	for(int i = 1; i <= n; i ++)
 	{
 		if(a[i] == '0')cnt += -1;
 		else cnt += 1;
 		
 		if(cnt < 0)	b[i] = i;
 		else
 		{
 			if(flag[cnt + 1] != 0)
 			{
 				b[i] = i - flag[cnt + 1];
			}
			else
			{
				flag[cnt] = i;
				b[i] = 0;
			}
		}
	}
	
	memset(flag,0,sizeof(flag));
	cnt = 0;
	for(int  i = n; i >= 1; i --)
	{
		if(a[i] == '0')cnt += -1;
		else cnt += 1;
		
		if(cnt > 0)c[i] = n - i + 1;
		else
		{
			if(flag[-cnt + 1] != 0)
			{
				c[i] = flag[-cnt + 1] - i;
			}
			else
			{
				flag[-cnt] = i;
				c[i] = 0;
			}
		}
	}
	
	ll ma = 0;
	for(int i = 1; i < n; i ++)
	{
		if(b[i] > 0 && c[i + 1] > 0)
		ma= max(ma,b[i] + c[i + 1]);
	}
	
	cout << ma << endl;
	
	
	return 0;
 	
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值