jzoj P2153【2017.7.7普及】串

来源:互联网 发布:linux 改名字命令 编辑:程序博客网 时间:2024/05/16 13:51

题目大意:
给定一个0-1串,请找到一个尽可能长的子串,其中包含的0与1的个数相等。

30%的数据 串的长度<20
100%的数据 长度不超过1000000
保证字符串只出现0,1

题解:
不难发现,前缀和然后强行枚举,30分到手,不过这100分嘛
就要稍微优美一点点,如果走到第i步的是0,就+1,是1则-1
设走到了第i步,sum[i]=x,到了第j步,sum[j]还是等于x,这时候我们可以知道,中间
i+1到j步时没有发生变化的,即0,1数量相持平。
然后我们发现
最小的x是串为1000000个1,这时x=-1000000
最大的x则串为1000000个0,这时x=1000000
不过如果要持平,
则x
最大为 1000000/2=500000
最小为-1000000/2=-500000
这时候我们可以直接开个比较大的桶去撸掉所有的情况….
然后找出能满足持平的情况的最左边跟最右边,然后在其中找出区间最长的串- -
然后100分就优美的到手了
~~~~~~~

var    sum:array [0..1000001] of longint;    a:Array [-1000001..1000001,1..2] of longint;    i,n,ans,max:longint;    s:ansistring;begin    assign(input,'string.in'); reset(input);    assign(output,'string.out');rewrite(output);    readln(s);    n:=length(s);    for i:=1 to n do      if s[i]='0' then sum[i]:=sum[i-1]+1                  else sum[i]:=sum[i-1]-1;    for i:=0 to n do        if sum[i]<=500000 then a[sum[i],2]:=i;    for i:=n downto 0 do a[sum[i],1]:=i;    for i:=-500000 to 500000 do      if a[i,2]-a[i,1]>max then max:=a[i,2]-a[i,1];    writeln(max);    close(input); close(output);end.

~~~~~~~~