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.

 

posted @ 2015-06-10 11:21  rpSebastian  阅读(286)  评论(0编辑  收藏  举报