题目描述:
1393 0和1相等串
给定一个0-1串,请找到一个尽可能长的子串,其中包含的0与1的个数相等。
输入
一个字符串,只包含01,长度不超过1000000。输出
一行一个整数,最长的0与1的个数相等的子串的长度。输入样例
1011输出样例
2
思路:
统计出前i个数中0/1的个数,然后对于个数相等的区间满足sum1[y]-sum1[x-1]==sum0[y]-sum0[x-1];
即sum1[y]-sum0[y]==sum1[x-1]-sum0[x-1],求出每项i的sum1-sum0,然后排个序找距离最远的相等值即可,复杂度O(NlogN)。
O(N)的算法,首先,该类题目为了方便处理,可以将0转换为-1,前缀和,然后即求相等值的最大距离,
求相等值的最大距离这里可以用桶的思想,记录1~1e6每个值的最小下标和最大下表。
代码实现:O(NlogN)
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=1e6+100;
int arr[N],mak[N];
int sum1[N],sum0[N];
pair<int,int> sum[N];
int main() {
freopen("E:\\io.txt","r",stdin);
string str;
cin>>str;
int n=str.length();
for(int i=1; i<=n; i++) {
if(str[i-1]=='1')sum1[i]=1;
else sum0[i]=1;
}
for(int i=1; i<=n; i++) {
sum1[i]=sum1[i-1]+sum1[i];
sum0[i]=sum0[i-1]+sum0[i];
}
//sum1[y]-sum1[x-1]==sum0[y]-sum0[x-1];
//sum1[y]-sum0[y]==sum1[x-1]-sum0[x-1];
for(int i=1; i<=n; i++)sum[i].first=sum1[i]-sum0[i],sum[i].second=i;
stable_sort(sum,sum+1+n);
int ans=0;
for(int i=0; i<n; i++) {
int pos=i;
int l=i,r=n;
while(l<=r) {
int mid=(l+r)/2;
if(sum[mid].first<sum[i].first)l=mid+1;
else if(sum[mid].first==sum[i].first) {
l=mid+1;
pos=mid;
} else r=mid-1;
}
ans=max(ans,sum[pos].second-sum[i].second);
}
cout<<ans<<endl;
return 0;
}
O(N)解法:
几个易错点:直接映射的化映射值可能为负数,要加一个偏移量,然后 原来的 0 现在变成
1e6。
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e6+100;
int arr[N],mak[N];
int sum[N];
pair<int,int> c[N];
int main() {
//freopen("E:\\io.txt","r",stdin);
for(int i=0;i<=2000000;i++)c[i].second=-INF,c[i].first=INF;
string str;
cin>>str;
int n=str.length();
for(int i=1;i<=n;i++){
if(str[i-1]=='0')arr[i]=-1;
else arr[i]=1;
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+arr[i];
for(int i=1;i<=n;i++)sum[i]+=1e6;
c[1000000].first=0;
for(int i=1;i<=n;i++){
if(i<c[sum[i]].first)c[sum[i]].first=i;
if(i>c[sum[i]].second)c[sum[i]].second=i;
}
int ans=0;
for(int i=0;i<=2e6;i++)ans=max(ans,c[i].second-c[i].first);
cout<<ans<<endl;
return 0;
}
The end