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.