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;
}



京公网安备 11010502036488号