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