zoukankan      html  css  js  c++  java
  • bzoj3413

    SAM好题,显然我们不能与每个后缀都去算LCP

    考虑对询问串每一位算贡献,先构建出逆序构建自动机,这样我们得到了原串的后缀树(parent树)

    根据parent树的定义,一个节点对应字符串出现的位置对应该节点的right集合也就是子树right集合的并

    某些节点代表了一个后缀,我们从开头到结尾编号为1~n;这样求出每个节点的子树内,代表后缀的节点所代表的后缀编号最小是多少,记作mi[]

    然后对于每个询问串在自动机上匹配(逆序),设最终匹配到的点为x

    由于每个子串一定是某个后缀的某个前缀

    如果匹配成功了,说明匹配到mi[x]这个后缀就结束了,否则会一直匹配下去,我们假设匹配到n+1结束

    设最终匹配到的后缀为m,显然,从x到root上我们计算每条边的贡献

    对于边(fa[a],a),边上的每个字符的比较次数贡献显然就是a子树内代表后缀编号小于等于m的节点个数

    裸的想法可以用dfs序+主席树来完成

    最后我们答案还要+x-1,因为比较失败也算是一次比较……

      1 type node=record
      2        po,next:longint;
      3      end;
      4      point=record
      5        l,r,s:longint;
      6      end;
      7 
      8 var tree:array[0..200010*20] of point;
      9     e:array[0..200010] of node;
     10     go:array[0..200010,'0'..'9'] of longint;
     11     mi,b,h,p,l,r,fa,mx,w:array[0..200010] of longint;
     12     cl,n,m,x,y,i,j,k,last,t,len:longint;
     13     fl:boolean;
     14     s:ansistring;
     15     ans:int64;
     16 
     17 function lowbit(x:longint):longint;
     18   begin
     19     exit(x and (-x));
     20   end;
     21 
     22 function min(a,b:longint):longint;
     23   begin
     24     if a>b then exit(b) else exit(a);
     25   end;
     26 
     27 procedure ins(x,y:longint);
     28   begin
     29     inc(len);
     30     e[len].po:=y;
     31     e[len].next:=p[x];
     32     p[x]:=len;
     33   end;
     34 
     35 procedure add(c:char);
     36   var p,q,np,nq:longint;
     37   begin
     38     p:=last;
     39     inc(t); np:=t; last:=t;
     40     mx[np]:=mx[p]+1;
     41     w[np]:=i;
     42     while (p<>0) and (go[p,c]=0) do
     43     begin
     44       go[p,c]:=np;
     45       p:=fa[p];
     46     end;
     47     if p=0 then fa[np]:=1
     48     else begin
     49       q:=go[p,c];
     50       if mx[q]=mx[p]+1 then fa[np]:=q
     51       else begin
     52         inc(t); nq:=t;
     53         mx[nq]:=mx[p]+1;
     54         go[nq]:=go[q];
     55         fa[nq]:=fa[q];
     56         fa[q]:=nq; fa[np]:=nq;
     57         while go[p,c]=q do
     58         begin
     59           go[p,c]:=nq;
     60           p:=fa[p];
     61         end;
     62       end;
     63     end;
     64   end;
     65 
     66 procedure dfs(x:longint);
     67   var i,y:longint;
     68   begin
     69     inc(len);
     70     b[len]:=x;
     71     mi[x]:=w[x];
     72     if w[x]=0 then mi[x]:=10000007;
     73  //   writeln(x,' ',fa[x],':',w[x]);
     74     l[x]:=len;
     75     i:=p[x];
     76     while i<>0 do
     77     begin
     78       y:=e[i].po;
     79       dfs(y);
     80       mi[x]:=min(mi[x],mi[y]);
     81       i:=e[i].next;
     82     end;
     83     r[x]:=len;
     84    // writeln(mi[x]);
     85   end;
     86 
     87 function build(l,r:longint):longint;
     88   var m,q:longint;
     89   begin
     90     inc(len);
     91     if l=r then exit(len)
     92     else begin
     93       q:=len;
     94       m:=(l+r) shr 1;
     95       tree[q].l:=build(l,m);
     96       tree[q].r:=build(m+1,r);
     97       exit(q);
     98     end;
     99   end;
    100 
    101 function work(l,r,last,x:longint):longint;
    102   var m,q:longint;
    103   begin
    104     inc(len);
    105     q:=len;
    106     if l=r then tree[q].s:=tree[last].s+1
    107     else begin
    108       m:=(l+r) shr 1;
    109       if x<=m then
    110       begin
    111         tree[q].r:=tree[last].r;
    112         tree[q].l:=work(l,m,tree[last].l,x);
    113       end
    114       else begin
    115         tree[q].l:=tree[last].l;
    116         tree[q].r:=work(m+1,r,tree[last].r,x);
    117       end;
    118       tree[q].s:=tree[tree[q].l].s+tree[tree[q].r].s;
    119     end;
    120     exit(q);
    121   end;
    122 
    123 function ask(l,r,p,q:longint):longint;
    124   var m:longint;
    125   begin
    126     if (x>=r) then exit(tree[q].s-tree[p].s)
    127     else begin
    128       m:=(l+r) shr 1;
    129       if x<=m then exit(ask(l,m,tree[p].l,tree[q].l))
    130       else exit(tree[tree[q].l].s-tree[tree[p].l].s+ask(m+1,r,tree[p].r,tree[q].r));
    131     end;
    132   end;
    133 
    134 begin
    135   readln(n);
    136   readln(s);
    137   last:=1; t:=1;
    138   for i:=n downto 1 do
    139     add(s[i]);
    140   for i:=1 to t do
    141     if fa[i]<>0 then ins(fa[i],i);
    142   len:=0;
    143   dfs(1);
    144   readln(m);
    145   len:=0;
    146   h[0]:=build(1,n);
    147   for i:=1 to t do
    148     if w[b[i]]=0 then h[i]:=h[i-1]
    149     else h[i]:=work(1,n,h[i-1],w[b[i]]);
    150   for i:=1 to m do
    151   begin
    152     readln(s);
    153     len:=length(s);
    154     j:=1;
    155     fl:=true;
    156     cl:=0;
    157     for k:=len downto 1 do
    158       if go[j,s[k]]=0 then
    159       begin
    160         while (go[j,s[k]]=0) and (j>0) do
    161         begin
    162           j:=fa[j];
    163           cl:=mx[j];
    164         end;
    165         if j=0 then j:=1
    166         else begin
    167           inc(cl);
    168           j:=go[j,s[k]];
    169         end;
    170         fl:=false;
    171       end
    172       else begin
    173         inc(cl);
    174         j:=go[j,s[k]];
    175       end;  //cl表示询问串从头开始最长匹配的长度
    176     if fl then x:=mi[j] else x:=n+1;
    177     ans:=0;
    178     if j>1 then
    179     begin
    180       y:=cl-mx[fa[j]];  // 这里要注意
    181       ans:=ans+int64(y)*int64(ask(1,n,h[l[j]-1],h[r[j]]));
    182       j:=fa[j];
    183     end;
    184     while j>1 do
    185     begin
    186       y:=mx[j]-mx[fa[j]];
    187       ans:=ans+int64(y)*int64(ask(1,n,h[l[j]-1],h[r[j]]));
    188       j:=fa[j];
    189     end;
    190     writeln(ans+x-1);
    191   end;
    192 end.
    View Code
  • 相关阅读:
    STL目录
    Hola!
    SWPUCTF 2019总结以及部分WP
    SQL手工注入基础篇
    JDK11,JDK12没有JRE的解决方法
    FJUT2019暑假周赛三部分题解
    FJUT2019暑假周赛一题解
    随笔1
    关于针对本校教务系统漏洞的一次信息检索
    KMP算法讲解
  • 原文地址:https://www.cnblogs.com/phile/p/4553298.html
Copyright © 2011-2022 走看看