之前我们给的SAM的例题,基本上是一个串建SAM的就能做的
如果要建多个串的SAM应该怎么做呢
首先看题,bzoj2780
我一开始的想法是SA以前的弄法,把串拼起来,中间加分隔符做SAM
这题确实可以这么做,这样根据SAM能识别所有子串的性质
而且每个节点都代表了唯一的一个串
每个询问串我们都能找到最终转移到哪(找不到就是没出现过)
问在多少个串出现过这就等价于在ST(s)的parent树的子树中,出现了多少种不同的权值
这显然可以维护dfs序,用经典的离线做法来搞(更好的写法见文末UPD)
1 type node=record 2 po,next:longint; 3 end; 4 5 var go:array[0..300010,1..27] of longint; 6 d,mx,fa,l,r,p,c,wh,w,fir,next:array[0..300010] of longint; 7 ans,a,b:array[0..60010] of longint; 8 e:array[0..300010] of node; 9 h,t,k,last,len,i,j,n,q,x:longint; 10 s,ss:ansistring; 11 12 function lowbit(x:longint):longint; 13 begin 14 exit(x and (-x)); 15 end; 16 17 function cmp(a,b:longint):boolean; 18 begin 19 exit(l[a]<l[b]); 20 end; 21 22 procedure swap(var a,b:longint); 23 var c:longint; 24 begin 25 c:=a; 26 a:=b; 27 b:=c; 28 end; 29 30 procedure sort(l,r:longint); 31 var i,j,x:longint; 32 begin 33 i:=l; 34 j:=r; 35 x:=a[(l+r) shr 1]; 36 repeat 37 while cmp(a[i],x) do inc(i); 38 while cmp(x,a[j]) do dec(j); 39 if not(i>j) then 40 begin 41 swap(a[i],a[j]); 42 swap(b[i],b[j]); 43 inc(i); 44 dec(j); 45 end; 46 until i>j; 47 if l<j then sort(l,j); 48 if i<r then sort(i,r); 49 end; 50 51 procedure build(x,y:longint); 52 begin 53 inc(len); 54 e[len].po:=y; 55 e[len].next:=p[x]; 56 p[x]:=len; 57 end; 58 59 procedure add(c,x:longint); 60 var p,q,np,nq:longint; 61 begin 62 p:=last; 63 inc(t); last:=t; np:=t; 64 w[np]:=x; mx[np]:=mx[p]+1; 65 while (p<>0) and (go[p,c]=0) do 66 begin 67 go[p,c]:=np; 68 p:=fa[p]; 69 end; 70 if p=0 then fa[np]:=1 71 else begin 72 q:=go[p,c]; 73 if mx[q]=mx[p]+1 then fa[np]:=q 74 else begin 75 inc(t); nq:=t; 76 mx[nq]:=mx[p]+1; 77 go[nq]:=go[q]; 78 fa[nq]:=fa[q]; 79 fa[q]:=nq; fa[np]:=nq; 80 while go[p,c]=q do 81 begin 82 go[p,c]:=nq; 83 p:=fa[p]; 84 end; 85 end; 86 end; 87 end; 88 89 procedure dfs(x:longint); 90 var i:longint; 91 begin 92 inc(h); 93 l[x]:=h; 94 d[h]:=w[x]; //dfs序 95 i:=p[x]; 96 while i<>0 do 97 begin 98 dfs(e[i].po); 99 i:=e[i].next; 100 end; 101 r[x]:=h; 102 end; 103 104 procedure work(x:longint); 105 begin 106 while x<=t do 107 begin 108 inc(c[x]); 109 x:=x+lowbit(x); 110 end; 111 end; 112 113 function ask(x:longint):longint; 114 begin 115 ask:=0; 116 while x>0 do 117 begin 118 ask:=ask+c[x]; 119 x:=x-lowbit(x); 120 end; 121 end; 122 123 begin 124 readln(n,q); 125 for i:=1 to n do 126 begin 127 readln(ss); 128 len:=length(ss); 129 for j:=1 to len do //拼接 130 begin 131 s:=s+ss[j]; 132 inc(t); wh[t]:=i; 133 end; 134 if i<>n then 135 begin 136 s:=s+chr(97+26); 137 inc(t); 138 end; 139 end; 140 len:=length(s); 141 t:=1; last:=1; 142 for i:=len downto 1 do 143 add(ord(s[i])-96,wh[i]); 144 145 len:=0; 146 for i:=2 to t do //构建树 147 build(fa[i],i); 148 149 dfs(1); 150 for i:=1 to q do 151 begin 152 readln(s); 153 j:=1; 154 len:=length(s); 155 for k:=len downto 1 do //每个询问串最终转移到哪 156 begin 157 x:=ord(s[k])-96; 158 if go[j,x]=0 then 159 begin 160 j:=0; 161 break; 162 end 163 else j:=go[j,x]; 164 end; 165 a[i]:=j; 166 b[i]:=i; 167 end; 168 for i:=t downto 2 do //经典的离线做法 169 begin 170 next[i]:=fir[d[i]]; 171 fir[d[i]]:=i; 172 end; 173 for i:=1 to n do 174 if fir[i]<>0 then work(fir[i]); 175 sort(1,q); 176 j:=1; 177 while a[j]=0 do inc(j); 178 for i:=1 to t do 179 begin 180 while (j<=q) and (l[a[j]]=i) do 181 begin 182 ans[b[j]]:=ask(r[a[j]])-ask(i-1); 183 inc(j); 184 end; 185 if d[i]<>0 then 186 if next[i]<>0 then work(next[i]); 187 end; 188 for i:=1 to q do 189 writeln(ans[i]); 190 end.