zoukankan      html  css  js  c++  java
  • 【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 
  • 相关阅读:
    网络系统集成实习——第四天——2017.9.10
    网络系统集成实习——第三天——2017.9.9
    网络系统集成实习——第二天——2017.9.8
    网络系统集成实习——第一天——2017.9.6
    如何查找文献及规范参考文献引用格式(以石家庄铁道大学图书馆为例)
    MATLAB数值分析实验
    MATLAB常微分方程的数值解法
    MATLAB数值积分法
    【工匠大道】博客园小技巧
    【夯实PHP基础】PHP 面向对象
  • 原文地址:https://www.cnblogs.com/myx12345/p/6411454.html
Copyright © 2011-2022 走看看