[BZOJ3879] SvT

来源:互联网 发布:海阔淘宝客助手 编辑:程序博客网 时间:2024/06/03 19:16

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=3879

题目大意

给定一个字符串
每次询问这个字符串得一些后缀两两之间的lcp之和

题解

建立反串的SAM得到后缀树
求点间的LCP转化为LCA
每次建立虚树就好了

const    maxn=500005;type    data=record    fa,len,key:longint;    tranc:array[0..26]of longint;    end;var    x:array[0..3*maxn]of data;    w:array[0..6*maxn,1..2]of longint;    fa,t,pos,y,dep,z,clear:array[0..3*maxn]of longint;    size:array[0..3*maxn]of longint;    st:array[0..3*maxn,0..20]of longint;    i,j,k:longint;    n,m,tot,tail,len,a,b,top,tt:longint;    stt:ansistring;    sum:int64;procedure sort(l,r:longint);var i,j,a,b:longint;begin    i:=l; j:=r; a:=pos[z[(l+r)div 2]];    repeat        while pos[z[i]]<a do inc(i);        while a<pos[z[j]] do dec(j);        if not (i>j) then        begin b:=z[i]; z[i]:=z[j]; z[j]:=b; inc(i); dec(j); end;    until i>j;    if l<j then sort(l,j);    if i<r then sort(i,r);end;procedure sort1(l,r:longint);var i,j,a,b:longint;begin    i:=l; j:=r; a:=pos[clear[(l+r)div 2]];    repeat        while pos[clear[i]]<a do inc(i);        while a<pos[clear[j]] do dec(j);        if not (i>j) then        begin b:=clear[i]; clear[i]:=clear[j]; clear[j]:=b; inc(i); dec(j); end;    until i>j;    if l<j then sort(l,j);    if i<r then sort(i,r);end;procedure insert(a:longint);var p,np,q,nq:longint;begin    inc(tot); np:=tot; p:=tail; x[np].len:=x[p].len+1; x[np].key:=1;    while (p<>0)and(x[p].tranc[a]=0) do        begin            x[p].tranc[a]:=np;            p:=x[p].fa;        end;    if x[p].tranc[a]=0    then x[p].tranc[a]:=np    else        begin            q:=x[p].tranc[a];            if x[q].len=x[p].len+1            then x[np].fa:=q            else                begin                    inc(tot); nq:=tot; x[nq]:=x[q]; x[nq].key:=0;                    x[nq].len:=x[p].len+1;                    x[q].fa:=nq; x[np].fa:=nq;                    while (x[p].tranc[a]=q) do                        begin                            x[p].tranc[a]:=nq;                            p:=x[p].fa;                        end;                end;        end;    tail:=np;end;procedure init(a,b:longint);begin    w[len,1]:=b;    if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len;    w[a,1]:=len; inc(len);end;procedure dfs(a:longint);var tt:longint;begin    tt:=w[a,2]; inc(len); pos[a]:=len;    if x[a].key=1 then y[n-x[a].len+1]:=a;    while tt<>0 do        begin            dep[w[tt,1]]:=dep[a]+1;            dfs(w[tt,1]);            tt:=w[tt,2];        end;end;function lca(a,b:longint):longint;var i:longint;begin    if dep[a]<dep[b] then begin i:=a; a:=b; b:=i; end;    for i:=20 downto 0 do        if dep[st[a,i]]>=dep[b]        then a:=st[a,i];    if a=b then exit(a);    for i:=20 downto 0 do        if st[a,i]<>st[b,i]        then begin a:=st[a,i]; b:=st[b,i]; end;    exit(st[a,0]);end;procedure solve(a:longint);var tt:longint;begin    tt:=w[a,2];    while tt<>0 do        begin            solve(w[tt,1]);                     size[a]:=size[a]+size[w[tt,1]];            tt:=w[tt,2];        end;    sum:=sum+(int64(x[a].len-x[x[a].fa].len)*(size[a]-1)*(size[a]))div 2;end;begin       readln(n,m);    readln(stt); tot:=0; tail:=0;    for i:=n downto 1 do        insert(ord(stt[i])-96);    len:=tot+1;    for i:=1 to tot do        begin init(x[i].fa,i); st[i,0]:=x[i].fa; end;    len:=0; dep[0]:=1; dfs(0);    for j:=1 to 20 do        for i:=1 to tot do            st[i,j]:=st[st[i,j-1],j-1];    fillchar(size,sizeof(size),0);    for i:=1 to m do        begin            read(a); sum:=0; clear[0]:=1; clear[1]:=0;            for j:=1 to a do                begin read(z[j]); size[y[z[j]]]:=1; z[j]:=y[z[j]]; end;            sort(1,a);            top:=1; t[top]:=0;            for j:=1 to a do                begin                    if z[j]=z[j-1] then continue;                    tt:=lca(z[j],t[top]);                    while dep[t[top]]>dep[tt] do                        begin                            if dep[t[top-1]]<=dep[tt]                            then                                begin                                    fa[t[top]]:=tt;                                    size[tt]:=size[tt]+size[t[top]];                                    dec(top);                                                                       if t[top]<>tt then begin inc(top); t[top]:=tt; inc(clear[0]); clear[clear[0]]:=tt; end;                                    break;                                end;                            fa[t[top]]:=t[top-1];                            size[t[top-1]]:=size[t[top-1]]+size[t[top]];                            dec(top);                        end;                    inc(top); t[top]:=z[j]; inc(clear[0]); clear[clear[0]]:=z[j];                end;            while top>1 do                begin                    fa[t[top]]:=t[top-1];                    size[t[top-1]]:=size[t[top-1]]+size[t[top]];                    dec(top);                end;            sum:=0;            for j:=1 to clear[0] do                sum:=sum+(int64(x[clear[j]].len-x[fa[clear[j]]].len)*(size[clear[j]]-1)*size[clear[j]])div 2;            writeln(sum);            for j:=1 to clear[0] do                begin size[clear[j]]:=0; fa[clear[j]]:=0; end;        end;end.
0 0
原创粉丝点击