Crazy Binary String
这题应该使用前缀和,做一次前缀和之后,我们首先会想到,就是一个一个的比较,n个不同前缀的最大substring,但是立马pass,复杂度n^2 / 2 ,和n^2没什么区别, 所以我们需要另一个想法。
首先,我们应该把0值用-1替换,原因很明显,如果我们要使用值来代表某一段的情况,0值是没有意义的,比如字符串t  0 1 0 1 0 1 ,到第6位,它的零一相等,如果我们用前缀和发现,0没有什么意义,如果要用0,我们还需要考虑长度,长度的值和1的总数的差,才是0的数目,很麻烦。
替换之后,经过观察, 我们发现,如果我们只记录某个前缀第一次出现的位置,和下一次出现的位置,我们就知道,这两个相同前缀之间的substring的的零一数目是相同的。
但是这样做有一个很大的弊端,比如某一个序列里面的 0 0 0 1 1 1 ,经过前缀和是 -1 -2 -3 -2 -1 0,很明显,我们还需要统计前缀和中值为0的长度,这才是正确答案。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

const int maxn=1e5+10;
int n;
char t[maxn];
int sum[maxn],dis[2*maxn];

int main()
{
    int ans=0,c0=0,c1=0;
    memset(dis,-1,sizeof(dis));
    scanf("%d",&n);
    scanf("%s",t+1);
    for (int i=1;i<n+1;i++) {
        if (t[i]=='0') {
            sum[i]=sum[i-1]-1;
            c0++;
        }
        else {
            sum[i]=sum[i-1]+1;
            c1++;
        }
        if (dis[sum[i]+maxn]==-1) {
            dis[sum[i]+maxn]=i;
        }
        else {
            ans=max(ans,i-dis[sum[i]+maxn]);
        }
        if (sum[i]==0) {
            ans=max(ans,i);
        }
    }
    printf("%d %d\n",ans,min(c0,c1)*2);
    return 0;
}