前缀和(狼和野牛)

位于欧洲中部的赫希费尔登狩猎保护区生活着许多动物,雄壮的野牛和凶狠的狼群之间保持着一种平衡,当野牛的数量和狼群一样多时,它们彼此互不侵犯相安无事,但只要狼的数量多于野牛狼群就会攻击牛群,而野牛数量占多数时,它们会驱逐狼群到别的地方。

当地的统计学家把牛群和狼群分布通过0和1表示为一个字符串S,S的字串可以表示一个区域内的牛和狼总数,请你根据这个统计字符串,判断出来这个保护区内能共存最多头野牛和狼的区域,该区域的牛群和狼群总数是多少。

输入

一个字符串,只包含01,长度不超过1000000。

输出

一行一个整数,最长的0与1的个数相等的子串的长度。

样例输入 Copy

1011

样例输出 Copy

2

提示

1. 样例解释
对于1011而言,它表示保护区内分布情况为:[牛,狼,牛,牛]
那么最多只有[狼,牛]这2只动物存在于某个区域内,所以结果为2
2. 数据范围
对于10%的数据,字符串长度≤10;
对于100%的数据,字符串长度≤1000000。
 
题目大意:就是找一个字符串中的最长字串(字串要满足01相等)
解析:

0看成-1,把1看成+1,则一个子串可以选当且仅当这个串里(区间)的数字之和为0。区间和可以表

示成两个前缀和的差,而两个前缀和的差为0即两个前缀和相等,记录前缀和为x的最早出现位置

f[x]

对于一个前缀和s[i],如果f[s[i]]<i则第f[s[i]]+1个字符到第i个字符组成的串就是一个合法解,且比它短

的解不会计入答案,用这个长度更新答案即可

就是找前缀和为0,或者前缀和相等中间夹着的。(……3……3……)两个3中间的,或者是(……0……)就是0前面的。

AC代码1:(用mp标记前缀和)

 

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
typedef long long ll;
const int maxn = 1e7+100;
char a[maxn];
int sum[maxn];
unordered_map<int,int>mp;
int main()
{
    gets(a+1);
    int t=strlen(a+1);
    for(int i=1;i<=t;i++){
        if(a[i]=='0'){
            sum[i]=sum[i-1]-1;
        }
        if(a[i]=='1'){
            sum[i]=sum[i-1]+1;
        } 
    }
    int ans=0;
    for(int i=1;i<=t;i++){
        if(sum[i]!=0&&!mp.count(sum[i])){
            mp[sum[i]]=i;//因为是最长所以找第一次出现的sum[i]
        }
        else
        ans=max(ans,i-mp[sum[i]]);
    }
    printf("%d",ans); 
    return 0;
}

 

AC代码2:数组标记:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
typedef long long ll;
const int maxn = 1e7+10;
char a[maxn];
int vis[maxn];
int main()
{
    scanf("%s",a+1);
    int t=strlen(a+1);
    int sum=0;
    int ans=0;
    sum=t; 
    for(int i=1;i<=t;i++){
        if(a[i]=='0'){
            sum--;
        }
        if(a[i]=='1'){
            sum++;
        }   
        if(sum!=t&&vis[sum]==0){
            vis[sum]=i;
        }
        else{
            ans=max(i-vis[sum],ans);
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

 

 

posted @ 2020-01-09 09:01  lipu123  阅读(354)  评论(0编辑  收藏  举报