【BZOJ1717&POJ3261】Milk Patterns(后缀数组,二分)

题意:求字符串的可重叠的k次最长重复子串

n<=20000 a[i]<=1000000

思路:后缀数组+二分答案x,根据height分组,每组之间的height>=x

因为可以重叠,所以只要判断是否有一组的height个数>=k即可

  1 var sa,rank,x,y,a,wc,wd,height:array[0..1100000]of longint;
  2     n,m,i,l,r,mid,last,k1:longint;
  3  
  4 procedure swap(var x,y:longint);
  5 var t:longint;
  6 begin
  7  t:=x; x:=y; y:=t;
  8 end;
  9  
 10 function cmp(a,b,l:longint):boolean;
 11 begin
 12  exit((y[a]=y[b])and(y[a+l]=y[b+l]));
 13 end;
 14  
 15 procedure getsa(n:longint);
 16 var i,j,p:longint;
 17 begin
 18  for i:=0 to n-1 do
 19  begin
 20   x[i]:=a[i];
 21   inc(wc[a[i]]);
 22  end;
 23  for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 24  for i:=n-1 downto 0 do
 25  begin
 26   dec(wc[x[i]]);
 27   sa[wc[x[i]]]:=i;
 28  end;
 29  j:=1; p:=1;
 30  while p<n do
 31  begin
 32   p:=0;
 33   for i:=n-j to n-1 do
 34   begin
 35    y[p]:=i; inc(p);
 36   end;
 37   for i:=0 to n-1 do
 38    if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end;
 39   for i:=0 to n-1 do wd[i]:=x[y[i]];
 40   for i:=0 to m-1 do wc[i]:=0;
 41   for i:=0 to n-1 do inc(wc[wd[i]]);
 42   for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 43   for i:=n-1 downto 0 do
 44   begin
 45    dec(wc[wd[i]]);
 46    sa[wc[wd[i]]]:=y[i];
 47   end;
 48   for i:=0 to n do swap(x[i],y[i]);
 49   p:=1; x[sa[0]]:=0;
 50   for i:=1 to n-1 do
 51    if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1
 52     else begin x[sa[i]]:=p; inc(p); end;
 53   j:=j*2;
 54   m:=p;
 55  end;
 56 end;
 57  
 58 procedure getheight(n:longint);
 59 var i,k,j:longint;
 60 begin
 61  for i:=1 to n do rank[sa[i]]:=i;
 62  k:=0;
 63  for i:=0 to n-1 do
 64  begin
 65   if k>0 then dec(k);
 66   j:=sa[rank[i]-1];
 67   while a[i+k]=a[j+k] do inc(k);
 68   height[rank[i]]:=k;
 69  end;
 70 end;
 71  
 72 function isok(x:longint):boolean;
 73 var s,i:longint;
 74 begin
 75  s:=1;
 76  for i:=1 to n do
 77  begin
 78   if height[i]<x then
 79   begin
 80    if s>=k1 then exit(true);
 81    s:=1;
 82   end
 83    else inc(s);
 84  end;
 85  if s>=k1 then exit(true);
 86  exit(false);
 87 end;
 88  
 89 begin
 90  
 91  while not eof do
 92  begin
 93   fillchar(a,sizeof(a),0);
 94   fillchar(sa,sizeof(sa),0);
 95   fillchar(rank,sizeof(rank),0);
 96   fillchar(x,sizeof(x),0);
 97   fillchar(y,sizeof(y),0);
 98   fillchar(height,sizeof(height),0);
 99   fillchar(wc,sizeof(wc),0);
100   fillchar(wd,sizeof(wd),0);
101   readln(n,k1);
102   if n=0 then break;
103   for i:=0 to n-1 do
104   begin
105    read(a[i]);
106    inc(a[i]);
107   end;
108   a[n]:=0; m:=1000001;
109   getsa(n+1);
110   getheight(n);
111   l:=1; r:=n; last:=0;
112   while l<=r do
113   begin
114    mid:=(l+r)>>1;
115    if isok(mid) then begin last:=mid; l:=mid+1; end
116     else r:=mid-1;
117   end;
118   writeln(last);
119  // for i:=0 to n do writeln(height[i]);
120  end;
121  
122  
123  
124 end.
125 

 

posted on 2017-02-17 20:35  myx12345  阅读(148)  评论(0编辑  收藏  举报

导航