【BZOJ1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 (二分+SA)

求重复k次的最长重复子串,解法见罗穗骞大神的后缀数组论文

  1 const maxn=100419;
  2  
  3 var
  4  x,y,rank,sa,h,s,num,c:array[0..maxn] of longint;
  5  n,time:longint;
  6  
  7 function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end;
  8 function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end;
  9 procedure make;
 10 var i,j,p,tot:longint;
 11 begin
 12  p:=1;
 13  while p<n do
 14   begin
 15    fillchar(c,sizeof(c),0);
 16    for i:= 1 to n-p do y[i]:=rank[i+p];
 17    for i:= n-p+1 to n do y[i]:=0;
 18    for i:= 1 to n do inc(c[y[i]]);
 19    for i:= 1 to n do inc(c[i],c[i-1]);
 20    for i:= 1 to n do
 21     begin
 22      sa[c[y[i]]]:=i;
 23      dec(c[y[i]]);
 24     end;
 25    fillchar(c,sizeof(c),0);
 26    for i:= 1 to n do x[i]:=rank[i];
 27    for i:= 1 to n do inc(c[x[i]]);
 28    for i:= 1 to n do inc(c[i],c[i-1]);
 29    for i:= n downto 1 do
 30     begin
 31      y[sa[i]]:=c[x[sa[i]]];
 32      dec(c[x[sa[i]]]);
 33     end;
 34    for i:= 1 to n do sa[y[i]]:=i;
 35    tot:=1;
 36    rank[sa[1]]:=1;
 37    for i:= 2 to n do
 38     begin
 39      if (x[sa[i]]<>x[sa[i-1]]) or (x[sa[i]+p]<>x[sa[i-1]+p]) then inc(tot);
 40      rank[sa[i]]:=tot;
 41     end;
 42    p:=p<<1;
 43   end;
 44 end;
 45  
 46 procedure makeht;
 47 var i,j,p:longint;
 48 begin
 49  h[1]:=0; p:=0;
 50  for i:= 1 to n do
 51   begin
 52    p:=max(p-1,0);
 53    if rank[i]=1 then continue;
 54    j:=sa[rank[i]-1];
 55    while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p);
 56    h[rank[i]]:=p;
 57   end;
 58 end;
 59  
 60 procedure init;
 61 var i,j,tot:longint;
 62  ch:char;
 63 begin
 64  readln(n,time);
 65  for i:= 1 to n do readln(s[i]);
 66  for i:= 1 to n do x[i]:=s[i];
 67  fillchar(c,sizeof(c),0);
 68  for i:= 1 to n do inc(c[x[i]]);
 69  for i:= 1 to 180 do inc(c[i],c[i-1]);
 70  for i:= 1 to n do
 71   begin
 72    sa[c[x[i]]]:=i;
 73    dec(c[x[i]]);
 74   end;
 75  rank[sa[1]]:=1;
 76  tot:=1;
 77  for i:= 2 to n do
 78   begin
 79    if x[sa[i]]<>x[sa[i-1]] then inc(tot);
 80    rank[sa[i]]:=tot;
 81   end;
 82  make;
 83  makeht;
 84 end;
 85  
 86 function check(k:longint):boolean;
 87 var i,j,x,y:longint;
 88 begin
 89  i:=1;
 90  while i<=n do
 91   begin
 92    j:=i;
 93    while (j<n) and (h[j+1]>=k) do inc(j);
 94    if j-i+1>=time then exit(true);
 95    i:=j+1;
 96   end;
 97  exit(false);
 98 end;
 99  
100 procedure solve;
101 var l,r,mid,ans:longint;
102 begin
103  l:=0; r:=n>>1; ans:=0;
104  while l<=r do
105   begin
106    mid:=(l+r)>>1;
107    if check(mid) then
108     begin
109      l:=mid+1;
110      ans:=mid;
111     end
112    else r:=mid-1;
113   end;
114  writeln(ans);
115 end;
116  
117 Begin
118  init;
119  solve;
120 End.
View Code

 

posted @ 2014-12-16 20:23  Ecsy  阅读(155)  评论(0编辑  收藏  举报