zoukankan      html  css  js  c++  java
  • [BZOJ3238][Ahoi2013]差异解题报告|后缀数组

    Description

      先分析一下题目,我们显然可以直接算出sigma(len[Ti]+len[Tj])的值=(n-1)*n*(n+1)/2

      接着就要去算这个字符串中所有后缀的两两最长公共前缀总和

      首先可以想到后缀数组,我们计算好后缀数组之后再进行对height数组的计算

      对于以x,y开头的后缀,它们的最长公共前缀为min(height[sa[i]])(rank[x]<=i<=rank[y])

      但从以往习惯的height数组入手我们发现并没有办法解决这个问题

      不如换个角度思考,我们可以枚举这个最小的数

      我们定义一个区间内最小的height为数值最小的情况下下标最小的位置

      那么一个数是最小的height,当且仅当这个区间的左边界到它的位置中没有数值小于等于它的数,它的右边界到它的位置中没有数值小于它的数

      我们可以用单调栈处理处这个左边界和右边界最远可以到达的位置

      然后乘法原理计算出答案就可以了

      代码写得很长的样子...(不知道为什么别人的SA好像写得都比我短...


      1 program bzoj3238;
      2 const maxn=500010;
      3 var s,a,rank,sa,tmp,height,l,r,st:array[-1..maxn]of int64;
      4     ans,n:int64;
      5     ss:ansistring;
      6     i:longint;
      7 
      8 function max(a,b:longint):longint;
      9 begin
     10     if a>b then exit(a) else exit(b);
     11 end;
     12 
     13 function compare(x,y,p:longint):longint;
     14 begin
     15     while (x+p-1<n)and(y+p-1<n)and(a[x+p-1]=a[y+p-1]) do inc(p);
     16     exit(p-1);
     17 end;
     18 
     19 procedure Suffix_Array;
     20 var i,j,p,size,v0,v1,v00,v01:longint;
     21 begin
     22     if n>26 then size:=n else size:=26;
     23     for i:=0 to n-1 do rank[i]:=a[i];
     24     for i:=0 to size-1 do s[i]:=0;
     25     for i:=0 to n-1 do inc(s[a[i]]);
     26     for i:=1 to size-1 do inc(s[i],s[i-1]);
     27     for i:=n-1 downto 0 do
     28     begin
     29         dec(s[a[i]]);
     30         sa[s[a[i]]]:=i;
     31     end;
     32     j:=1;
     33     while j<=n do
     34     begin
     35         p:=0;
     36         for i:=n-j to n-1 do
     37         begin
     38             tmp[p]:=i;inc(p);
     39         end;
     40         for i:=0 to n-1 do if sa[i]-j>=0 then
     41         begin
     42             tmp[p]:=sa[i]-j;inc(p);
     43         end;
     44         for i:=0 to size-1 do s[i]:=0;
     45         for i:=0 to n-1 do inc(s[rank[i]]);
     46         for i:=1 to size-1 do inc(s[i],s[i-1]);
     47         for i:=n-1 downto 0 do
     48         begin
     49             dec(s[rank[tmp[i]]]);
     50             sa[s[rank[tmp[i]]]]:=tmp[i];
     51         end;
     52         p:=0;tmp[sa[0]]:=0;
     53         for i:=1 to n-1 do
     54         begin
     55             v0:=sa[i-1];v1:=sa[i];
     56             if v0+j<n then v00:=rank[v0+j] else v00:=-1;
     57             if v1+j<n then v01:=rank[v1+j] else v01:=-1;
     58             if (rank[v0]=rank[v1])and(v00=v01) then tmp[sa[i]]:=p else
     59             begin
     60                 inc(p);tmp[sa[i]]:=p;
     61             end;
     62         end;
     63         for i:=0 to n-1 do rank[i]:=tmp[i];
     64                 j:=j << 1;
     65     end;
     66 end;
     67 
     68 procedure Calc_Height;
     69 var i:longint;
     70 begin
     71     if rank[0]=0 then height[0]:=0 else height[0]:=compare(0,sa[rank[0]-1],1);
     72     for i:=1 to n-1 do
     73     if rank[i]=0 then height[i]:=0 else height[i]:=compare(i,sa[rank[i]-1],max(height[i-1],1));
     74 end;
     75 
     76 procedure Solve;
     77 var i,top:longint;
     78 begin
     79     height[-1]:=-maxlongint;
     80     st[0]:=-1;sa[-1]:=-1;top:=0;
     81     for i:=0 to n-1 do
     82     begin
     83         while height[sa[st[top]]]>=height[sa[i]] do dec(top);
     84         l[i]:=st[top];
     85         inc(top);st[top]:=i;
     86     end;
     87     st[0]:=n;sa[n]:=-1;top:=0;
     88     for i:=n-1 downto 0 do
     89     begin
     90         while height[sa[st[top]]]>height[sa[i]] do dec(top);
     91         r[i]:=st[top];
     92         inc(top);st[top]:=i;
     93     end;
     94     for i:=0 to n-1 do dec(ans,height[sa[i]]*(i-l[i])*(r[i]-i)*2);
     95     writeln(ans);
     96 end;
     97 
     98 begin
     99     readln(ss);
    100     n:=length(ss);
    101     for i:=1 to n do a[i-1]:=ord(ss[i])-96;
    102         for i:=1 to n do inc(ans,i*(n-1));
    103         Suffix_Array;
    104         Calc_Height;
    105         Solve;
    106 end.
     
     
  • 相关阅读:
    毕业设计预习:SM3密码杂凑算法基础学习
    毕业设计预习:maxplus2入门教程
    毕业设计预习:VHDL入门知识学习(一) VHDL程序基本结构
    网络对抗课题4.3.1 SQL注入原理与实践
    20135319zl内核模块编译报告
    20135319zl字符集报告
    20135319zl elf文件报告
    20135319zl软件破解报告
    linux内核分析综合总结
    Linux内核分析期中总结
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4428437.html
Copyright © 2011-2022 走看看