• Codechef2015 May


    用后缀自动机统计出出现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.
  • 相关阅读:
    [WPF]Win10便签软件
    [WPF]使用Fody提高效率
    [WPF]限制程序单例运行
    [WPF]创建系统栏小图标
    Run Performance Testing Which Was Distributed To Multiple Test Agents
    FxZ,C#开发职位面试测试题(30分钟内必须完成)
    BYS推荐MS前端PhoneCall面试问题整理-2
    BYS推荐MS前端PhoneCall面试问题整理-1
    LxNx前端F2F面试问题整理
    复杂DIV交错布局
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/4565540.html
Copyright © 2020-2023  润新知