Codechef2015 May - Chef and Strings (后缀自动机)
用后缀自动机统计出出现1~n次的串的数量f[i]
对于ans[k]=sigma(f[i]*C(i,k)) i>=k
1 const maxn=10008; 2 mo=1000000007; 3 var a,f,rig:array[0..maxn] of dword; 4 nt:array[0..maxn,'a'..'z'] of longint; 5 last,sum,i:dword; 6 s:ansistring; 7 eg:array[0..maxn*2] of record nt,v:dword; end; 8 lt:array[0..maxn] of dword; 9 el:dword; 10 11 time:array[0..maxn] of qword; 12 T,j,TT:dword; 13 ans:array[0..maxn] of qword; 14 C:array[-1..5000,-1..5000] of qword; 15 du,g:array[0..maxn] of longint; 16 b:array[0..1000000] of longint; 17 procedure SAM_init; inline; 18 begin 19 fillchar(f,sizeof(f),255); 20 fillchar(nt,sizeof(nt),255); 21 fillchar(a,sizeof(a),0); 22 fillchar(rig,sizeof(rig),0); 23 el:=0; 24 fillchar(lt,sizeof(lt),0); 25 fillchar(ans,sizeof(ans),0); 26 fillchar(du,sizeof(du),0); 27 fillchar(g,sizeof(g),0); 28 last:=0; sum:=0; 29 end; 30 31 procedure SAM_ins(ch:char); inline; 32 var next,p,np,q,nq:longint; 33 begin 34 inc(sum); p:=last; np:=sum; a[np]:=a[p]+1; last:=np; rig[np]:=1; 35 while (p<>-1) and (nt[p][ch]=-1) do begin nt[p][ch]:=np; p:=f[p]; end; 36 if p=-1 then f[np]:=0 else 37 begin 38 q:=nt[p][ch]; 39 if a[p]+1=a[q] then f[np]:=q else 40 begin 41 inc(sum); nq:=sum; a[nq]:=a[p]+1; 42 nt[nq]:=nt[q]; 43 f[nq]:=f[q]; f[q]:=nq; f[np]:=nq; 44 while (p<>-1) and (nt[p][ch]=q) do begin nt[p][ch]:=nq; p:=f[p]; end; 45 end; 46 end; 47 end; 48 49 procedure SAM_visit1; inline; 50 var i,l,r:longint; 51 c:char; 52 begin 53 for i:=0 to sum do 54 for c:='a' to 'z' do 55 if nt[i][c]<>-1 then inc(du[nt[i][c]]); 56 57 58 l:=1; r:=1; b[1]:=0; g[0]:=1; 59 while l<=r do 60 begin 61 for c:='a' to 'z' do 62 if nt[b[l]][c]<>-1 then 63 begin 64 dec(du[nt[b[l]][c]]); 65 inc(g[nt[b[l]][c]],g[b[l]]); 66 if du[nt[b[l]][c]]=0 then 67 begin 68 inc(r); 69 b[r]:=nt[b[l]][c]; 70 end; 71 end; 72 inc(l); 73 end; 74 for i:=1 to sum do inc(time[rig[i]],g[i]); 75 end; 76 procedure dfs(u:dword); 77 var i:dword; 78 begin 79 i:=lt[u]; 80 while i<>0 do 81 begin 82 dfs(eg[i].v); 83 rig[u]:=rig[u]+rig[eg[i].v]; 84 i:=eg[i].nt; 85 end; 86 end; 87 procedure add(u,v:dword); inline; 88 begin 89 inc(el); 90 eg[el].v:=v; 91 eg[el].nt:=lt[u]; 92 lt[u]:=el; 93 end; 94 procedure SAM_rig; inline; 95 begin 96 el:=0; 97 fillchar(lt,sizeof(lt),0); 98 for i:=1 to sum do add(f[i],i); 99 dfs(0); 100 end; 101 procedure main; inline; 102 var n,q,i,j:dword; 103 cnt:qword; 104 begin 105 if T<>1 then 106 begin 107 fillchar(time,sizeof(time),0); 108 SAM_init; 109 end; 110 readln(n,q); 111 readln(s); 112 SAM_init; 113 for i:=1 to n do SAM_ins(s[i]); 114 SAM_rig; 115 SAM_visit1; 116 for i:=1 to n do 117 for j:=i to n do ans[i]:=(ans[i]+C[j,i]*time[j]) mod mo; 118 for i:=1 to q do 119 begin 120 readln(j); 121 if j>n then writeln(0) else 122 writeln(ans[j]); 123 end; 124 end; 125 begin 126 C[0,0]:=1; 127 for i:=1 to 5000 do 128 for j:=0 to i do 129 begin 130 C[i,j]:=(c[i-1,j-1]+c[i-1,j]); 131 if C[i,j]>=mo then C[i,j]:=C[i,j]-mo; 132 end; 133 readln(T); 134 for TT:=1 to T do main; 135 end.