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
原文地址:https://www.cnblogs.com/phile/p/4553298.html