题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB
给定一个01串S,求出它的一个尽可能长的子串S[i..j],满足存在一个位置i<=x <=j, S[i..x]中0比1多,而S[x + 1..j]中1比0多。求满足条件的最长子串长度。
Input
一行包含一个只由0和1构成的字符串S。 S的长度不超过1000000。
Output
一行包含一个整数,表示满足要求的最长子串的长度。
Input示例
10
Output示例
0
思路:dp
枚举x的值,然后找[i,x]0比1多的最小i,[x+1,j]1比0多的最大j。问题在于咋找到i,和j;sum[i]表示[1,i]的前缀和,我们将0换成-1,那么当前sum[]<0的话肯定i=1;当前sum[]>=0的话,我们只要知道sum[]+1那个值对应的i并且位置最前,这样我们就有[i+1,x]的值小于0,为啥是sum[]+1;因为所有的序列都是-1,1。那么从一个值到另一个值都是连续变化的,必须先有sum[]+1,然后才会有sum[]+2,(前提是在sum[]>=0时)那么只要记录第一个sum[]+1出现的位置,同理找j;
1 #include<stdlib.h> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iostream> 5 #include<string.h> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 map<int,int>my; 10 char str[1000005]; 11 int ans[1000005]; 12 int sum[1000005]; 13 int dp1[1000005]; 14 int dp2[1000005]; 15 int main(void) 16 { 17 scanf("%s",str); 18 int i; 19 int l = strlen(str); 20 for(i = 0; i < l; i++) 21 { 22 if(str[i]=='0') 23 ans[i+1] = -1; 24 else ans[i+1] = 1; 25 } 26 int sum = 0; 27 for(i = 1; i <= l; i++) 28 { 29 sum += ans[i]; 30 if(sum < 0) 31 { 32 dp1[i] = 1; 33 } 34 else if(sum >= 0) 35 { 36 if(my.count(sum+1)) 37 { 38 dp1[i] = my[sum+1]+1; 39 } 40 else dp1[i] = -1; 41 if(!my.count(sum)) 42 { 43 my[sum] = i; 44 } 45 } 46 } 47 my.clear(); 48 sum = 0; 49 for(i = l; i >= 1; i--) 50 { 51 sum += ans[i]; 52 if(sum > 0) 53 { 54 dp2[i] = l; 55 } 56 else if(sum <= 0) 57 { 58 if(my.count(sum-1)) 59 { 60 dp2[i] = my[sum-1]-1; 61 } 62 else dp2[i] = -1; 63 if(!my.count(sum)) 64 { 65 my[sum] = i; 66 } 67 } 68 } 69 int maxx = 0; 70 for(i = 1; i <= l-1; i++) 71 { 72 if(dp1[i]!=-1&&dp2[i+1]!=-1) 73 { 74 maxx = max(maxx,dp2[i+1]-dp1[i]+1); 75 } 76 } 77 printf("%d ",maxx); 78 return 0; 79 }