[hdu7081]Pty loves book
建立ac自动机,令$S_{x}$为以根到$x$的路径所构成的字符串以及$L_{x}=|S_{x}|,W_{x}=\sum_{1\le i\le m,t_{i}为S_{x}的后缀}w_{i}$,那么不难得到有$W_{x}=\sum_{1\le i\le m,t_{i}=S_{x}}w_{i}+W_{fail_{x}}$,即可预处理出$W$
进一步的,令$pos(s)$为在其中查询$s$得到的最终节点,则有$f(s)=\sum_{i=1}^{|s|}W_{pos(s[1,i])}$
接下来,考虑再求出$F_{x}=\sum_{i=1}^{L_{x}}f(S_{x}[i,L_{x}])^{5}$,对于其中$i>L_{x}-L_{fail_{x}}$的部分即为$F_{fail_{x}}$,而剩下的部分即为$\sum_{i=1}^{L_{x}-L_{fail_{x}}}f(S_{x}[i,L_{x}])^{5}$,将其记为$G_{x}$
关于$G_{x}$,显然$f(S_{x}[i,L_{x}])=f(S_{x}[i,L_{x}))+W_{pos(S_{x}[i,L_{x}])}$,并特判$i=1$时的贡献(即$x$到根路径$W$之和的5次方),对于其他情况后者即$W_{fail_{x}}$
关于前者,即从$x$的父亲$fa$开始不断走到$fail_{fa}$直至$fail_{x}$的父亲为止的$G_{fa}$之和,但注意其中还多算了$i=1$时的答案,即去掉$f(S_{x}[1,L_{x}))+W_{fail_{x}}$
另外由于是5次方,需要求出$G_{x,p}=\sum_{i=1}^{L_{x}-L_{fail_{x}}}f(S_{x}[i,L_{x}])^{p}$,展开后即有
$$
G_{x,p}=\sum_{i=0}^{p}{p\choose i}W_{fail_{x}}^{i}\sum_{fa}G_{fa,p-i}+(\sum_{y在x到根路径上}W_{y})^{p}-(\sum_{y在x的父亲到根路径上}W_{x}+W_{fail_{x}})^{p}
$$
最终,不妨初始将$s$也加入自动机中,那么答案即$pos(s)$到根路径的$F$之和,可以计算
总复杂度为$o(5^{2}|s|)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define mod 1000000007 5 #define ll long long 6 queue<int>q; 7 int V,t,n,m,x,ans,C[6][6],fail[N],w[N],sum[N],G[N][6],F[N],ch[N][26]; 8 char s[N]; 9 int New(){ 10 int k=++V; 11 w[k]=0; 12 memset(G[k],0,sizeof(G[k])); 13 memset(ch[k],0,sizeof(ch[k])); 14 return k; 15 } 16 void add(int x){ 17 int k=1,l=strlen(s); 18 for(int i=0;i<l;i++){ 19 if (!ch[k][s[i]-'a'])ch[k][s[i]-'a']=New(); 20 k=ch[k][s[i]-'a']; 21 } 22 w[k]=(w[k]+x)%mod; 23 } 24 int main(){ 25 for(int i=0;i<6;i++){ 26 C[i][0]=C[i][i]=1; 27 for(int j=1;j<i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j]; 28 } 29 scanf("%d",&t); 30 while (t--){ 31 scanf("%s%d",s,&m); 32 V=ans=0,n=strlen(s); 33 New(),add(0); 34 for(int i=1;i<=m;i++){ 35 scanf("%s%d",s,&x); 36 add(x); 37 } 38 fail[1]=1; 39 q.push(1); 40 while (!q.empty()){ 41 int k=q.front(); 42 q.pop(); 43 for(int i=0;i<26;i++) 44 if (ch[k][i]){ 45 if (k==1)x=1; 46 else{ 47 x=fail[k]; 48 while ((x>1)&&(!ch[x][i]))x=fail[x]; 49 if (ch[x][i])x=ch[x][i]; 50 } 51 fail[ch[k][i]]=x; 52 w[ch[k][i]]=(w[ch[k][i]]+w[x])%mod; 53 sum[ch[k][i]]=(sum[k]+w[ch[k][i]])%mod; 54 q.push(ch[k][i]); 55 } 56 } 57 q.push(1); 58 while (!q.empty()){ 59 int k=q.front(); 60 q.pop(); 61 for(int i=0;i<26;i++) 62 if (ch[k][i]){ 63 x=ch[k][i]; 64 int s1=1,s2=1; 65 for(int p=1;p<6;p++){ 66 s1=(ll)s1*sum[x]%mod,s2=(ll)s2*(sum[k]+w[fail[x]])%mod; 67 G[x][p]=(s1-s2+mod)%mod; 68 } 69 if (fail[x]==1)G[x][0]=1; 70 for(int p=0;p<6;p++){ 71 int s=1; 72 for(int j=0;j<=p;j++){ 73 for(int fa=k;(fa!=1)&&(ch[fa][i]!=fail[x]);fa=fail[fa])G[x][p]=(G[x][p]+(ll)C[p][j]*s%mod*G[fa][p-j])%mod; 74 s=(ll)s*w[fail[x]]%mod; 75 } 76 } 77 F[x]=(F[fail[x]]+G[x][5])%mod; 78 q.push(x); 79 } 80 } 81 for(int i=1;i<=n;i++)ans=(ans+F[i+1])%mod; 82 printf("%d\n",ans); 83 } 84 return 0; 85 }