zoukankan      html  css  js  c++  java
  • bzoj3238

    都LCP了很显然是要用到后缀数组的

    显然前面的那个东西是可以直接算出来的

    关键在于LCP的和怎么快速的计算

    不难想到穷举height[i],然后判断这个height[i]可能成为多少对后缀的LCP

    考虑到LCP(i,j)=min(height[rank[i]+1~rank[j]]) 假定rank[i]<rank[j];

    假设height[l]是左边第一个小于height[i]的,height[r]是右边第一个小于height[i]的

    则height[i]是(i-l)(r-i)对后缀的LCP

    但这样有一个问题,相同height可能会被重复计算

    为了避免重复,我们定义height[r]是右边第一个不大于height[i]的

    这样就有两种方法来实现

    第一种是二分+rmq,但不幸的是我竟然写超时,而且我觉得容易出错

    第二种是利用单调队列,我们把height[i]对应的l,r定义为左右边界,记为l[i],r[i];

    计算左边界和右边界是相似的,这里我们讨论左边界

    假如height[j]<=height[k] (j>k) 那么对于之后的height[i],

    要么能延伸到k之前(height[i]<=height[j]),要么只能左边界就是j(height[i]>height[j]),不用比较height[k]

    显然我们要维护一个单调不降的队列就行了

    最后计算的时候注意用int64

      1 var rank,sa,y,q,x,sum,h,l,r:array[0..600010] of longint;
      2     s:ansistring;
      3     i,n,m,p,j,t:longint;
      4     ans,z:int64;
      5 
      6 function min(a,b:longint):longint;
      7   begin
      8     if a>b then exit(b) else exit(a);
      9   end;
     10 
     11 procedure suffix;
     12   var i,j,p:longint;
     13   begin
     14     for i:=1 to n do
     15     begin
     16       y[i]:=ord(s[i]);
     17       inc(sum[y[i]]);
     18     end;
     19     m:=255;
     20     for i:=1 to m do
     21       inc(sum[i],sum[i-1]);
     22     for i:=n downto 1 do
     23     begin
     24       sa[sum[y[i]]]:=i;
     25       dec(sum[y[i]]);
     26     end;
     27     p:=1;
     28     rank[sa[1]]:=1;
     29     for i:=2 to n do
     30     begin
     31       if y[sa[i]]<>y[sa[i-1]] then inc(p);
     32       rank[sa[i]]:=p;
     33     end;
     34     m:=p;
     35     j:=1;
     36     while m<n do
     37     begin
     38       fillchar(sum,sizeof(sum),0);
     39       y:=rank;
     40       p:=0;
     41       for i:=n-j+1 to n do
     42       begin
     43         inc(p);
     44         x[p]:=i;
     45       end;
     46       for i:=1 to n do
     47         if sa[i]>j then
     48         begin
     49           inc(p);
     50           x[p]:=sa[i]-j;
     51         end;
     52 
     53       for i:=1 to n do
     54       begin
     55         rank[i]:=y[x[i]];
     56         inc(sum[rank[i]]);
     57       end;
     58       for i:=1 to m do
     59         inc(sum[i],sum[i-1]);
     60       for i:=n downto 1 do
     61       begin
     62         sa[sum[rank[i]]]:=x[i];
     63         dec(sum[rank[i]]);
     64       end;
     65       p:=1;
     66       rank[sa[1]]:=1;
     67       for i:=2 to n do
     68       begin
     69         if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i]+j]<>y[sa[i-1]+j]) then inc(p);
     70         rank[sa[i]]:=p;
     71       end;
     72       m:=p;
     73       j:=j shl 1;
     74     end;
     75     h[1]:=0;
     76     p:=0;
     77     for i:=1 to n do
     78     begin
     79       if rank[i]=1 then continue;
     80       j:=sa[rank[i]-1];
     81       while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p);
     82       h[rank[i]]:=p;
     83       if p>0 then dec(p);
     84     end;
     85   end;
     86 
     87 function calc(i,x,y:int64):int64;
     88   begin
     89     exit(2*h[i]*(i-x)*(y-i));
     90   end;
     91 
     92 begin
     93   readln(s);
     94   n:=length(s);
     95   suffix;
     96   z:=n;
     97   ans:=(z+1)*z div 2*(z-1);
     98   t:=0;
     99   for i:=2 to n do
    100   begin
    101     while (t>0) and (h[q[t]]>=h[i]) do dec(t);
    102     if t=0 then l[i]:=1
    103     else l[i]:=q[t];
    104     inc(t);
    105     q[t]:=i;
    106   end;
    107   t:=0;
    108   for i:=n downto 2 do
    109   begin
    110     while (t>0) and (h[q[t]]>h[i]) do dec(t);  //注意右边界是第一个不大于的height,防止重复
    111     if t=0 then r[i]:=n+1
    112     else r[i]:=q[t];
    113     inc(t);
    114     q[t]:=i;
    115   end;
    116   for i:=2 to n do
    117     ans:=ans-calc(i,l[i],r[i]);
    118   writeln(ans);
    119 end.
    View Code
  • 相关阅读:
    M-CloneG-DFS-BFS-图
    M-WordB-BFS-DP
    Reverse Linked List II
    OpenCV 第二课 认识图像的存储结构
    Surf特征提取分析
    OpenCV 第一课(安装与配置)
    简单验证码识别(matlab)
    matlab中各种高斯相关函数
    SIFT特征提取分析
    斑点检测(LoG,DoG)(下)
  • 原文地址:https://www.cnblogs.com/phile/p/4473164.html
Copyright © 2011-2022 走看看