zoukankan      html  css  js  c++  java
  • 【BZOJ3238】差异(后缀数组,单调栈)

    题意:

    思路:显然len(t[i])+len(t[j])这部分的和是一定的

    那么问题就在于如何快速求出两两之间lcp之和

    考虑将它们排名后用SA可以很方便的求出lcp,且对答案没有影响,因为形式都是数对

    所以用SA求出height

    每个位置的height作为lcp的区间为扩展到最左最右,直到height[x]<height[i],height[y]<height[i]

    这样合法的左区间为[x+1,i],右区间为[i,y-1]

    考虑如何维护一个支持寻找最靠近当前位置的比当前位置上的数小的位置

    这个可以用两次单调栈维护

    但还要考虑到重复计算的情况,比如有多个最小值覆盖了全部区域

    我们可以在比较时其中一次取等号,一次不取

      1 var x,y,sa,rank,height,wc,wd,a:array[0..600000]of longint;
      2     l,r:array[1..600000]of int64;
      3     stk:array[1..600000]of longint;
      4     n,i,m,top:longint;
      5     ans,j:int64;
      6     ch:ansistring;
      7 
      8 function min(x,y:longint):longint;
      9 begin
     10  if x<y then exit(x);
     11  exit(y);
     12 end;
     13 
     14 function cmp(a,b,l:longint):boolean;
     15 begin
     16  exit((y[a]=y[b])and(y[a+l]=y[b+l]));
     17 end;
     18 
     19 procedure swap(var x,y:longint);
     20 var t:longint;
     21 begin
     22  t:=x; x:=y; y:=t;
     23 end;
     24 
     25 procedure getsa(n:longint);
     26 var i,j,p:longint;
     27 begin
     28  for i:=0 to n-1 do
     29  begin
     30   x[i]:=a[i];
     31   inc(wc[x[i]]);
     32  end;
     33  for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
     34  for i:=n-1 downto 0 do
     35  begin
     36   dec(wc[x[i]]);
     37   sa[wc[x[i]]]:=i;
     38  end;
     39  j:=1; p:=1;
     40  while p<n do
     41  begin
     42   p:=0;
     43   for i:=n-j to n-1 do
     44   begin
     45    y[p]:=i; inc(p);
     46   end;
     47   for i:=0 to n-1 do
     48    if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end;
     49   for i:=0 to n-1 do wd[i]:=x[y[i]];
     50   for i:=0 to m-1 do wc[i]:=0;
     51   for i:=0 to n-1 do inc(wc[wd[i]]);
     52   for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
     53   for i:=n-1 downto 0 do
     54   begin
     55    dec(wc[wd[i]]);
     56    sa[wc[wd[i]]]:=y[i];
     57   end;
     58   for i:=0 to n do swap(x[i],y[i]);
     59   p:=1; x[sa[0]]:=0;
     60   for i:=1 to n-1 do
     61    if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1
     62     else begin x[sa[i]]:=p; inc(p); end;
     63   j:=j<<1;
     64   m:=p;
     65  end;
     66 end;
     67 
     68 procedure getheight(n:longint);
     69 var i,j,k:longint;
     70 begin
     71  k:=0;
     72  for i:=1 to n do rank[sa[i]]:=i;
     73  for i:=0 to n-1 do
     74  begin
     75   if k>0 then dec(k);
     76   j:=sa[rank[i]-1];
     77   while a[i+k]=a[j+k] do inc(k);
     78   height[rank[i]]:=k;
     79  end;
     80 end;
     81 
     82 begin
     83  assign(input,'bzoj3238.in'); reset(input);
     84  assign(output,'bzoj3238.out'); rewrite(output);
     85  readln(ch);
     86  n:=length(ch);
     87  for i:=0 to n-1 do a[i]:=ord(ch[i+1])-ord('a')+1;
     88  a[n]:=0; m:=300;
     89  getsa(n+1);
     90  getheight(n);
     91  stk[1]:=1; height[1]:=-maxlongint; top:=1;
     92  for i:=2 to n do
     93  begin
     94   while (top>0)and(height[i]<height[stk[top]]) do dec(top);
     95   if stk[top]=1 then l[i]:=2
     96    else l[i]:=stk[top]+1;
     97   inc(top); stk[top]:=i;
     98  end;
     99 
    100  stk[1]:=n+1; height[n+1]:=-maxlongint; top:=1;
    101  for i:=n downto 2 do
    102  begin
    103   while (top>0)and(height[i]<=height[stk[top]]) do dec(top);
    104   if stk[top]=n+1 then r[i]:=n
    105    else r[i]:=stk[top]-1;
    106   inc(top); stk[top]:=i;
    107  end;
    108 
    109 
    110  ans:=int64(n-1)*int64(n)*(n+1) div 2;
    111  for i:=2 to n do ans:=ans-2*(-l[i]+i+1)*(r[i]-i+1)*height[i];
    112  //for i:=2 to n+1 do writeln(l[i],' ',r[i]);
    113  writeln(ans);
    114  close(input);
    115  close(output);
    116 end.
  • 相关阅读:
    《linux 内核全然剖析》 笔记 CODE_SPACE 宏定义分析
    Item 8:析构函数不要抛出异常 Effective C++笔记
    Eclipse经常使用快捷键
    多人即时战斗游戏服务端系列[2]--90坦克Online游戏对象介绍以及渲染机制
    STM8S awu及看门狗IWDG WWDG应用(转)
    使用STM8SF103 ADC采样电压(转)
    BHS-STM32工具系列
    STM32 FLASH模拟EEPROM 使用和优化(转)
    STM32+NRF24L01无线(转)
    像51一样操作STM32的IO(转)
  • 原文地址:https://www.cnblogs.com/myx12345/p/6721141.html
Copyright © 2011-2022 走看看