It's known to all that ZYB is godlike, so obviously he has a large number of titles, such as jskingjsking, bijingzybbijingzyb and nbazybnbazyb. ZYB likes his titles very much.

Each of ZYB's titles is a string consisting of lower case letters 'a'-'z''a'-'z' associated with a happiness value hihi, which shows how much ZYB likes this title. If you say any substring of some title with happiness value xx, he will get xx happiness points. Moreover, a string may appear in more than one title. In this case, the happiness points ZYB gets are multiplied. If the string you say is not the substring of any of his titles, he gets no happiness point.

For example, let's say ZYB has two titles: zybnbzybnb (with happiness value 3) and ybybybyb (with happiness value 5). If you say yy, bb or ybyb, ZYB will get 15 happiness points; if you say zz, zyzy or zybzyb, ZYB will only get 3 happiness points; if you say ybzybz or ybacybac he will get 0 happiness points.

One day, you find ZYB pretty sad. As a big fan of ZYB, you want to say a word to ZYB to cheer him up. However, ZYB is really busy, so you can only say no more than mm letters. As you haven't seen ZYB for a long time, you are so excited that you forget what you want to say, so you decide to choose to say a nonempty string no longer than mm and only containing 'a'-'z''a'-'z' with equal probability. You want to know the expectations of happiness points you will bring to ZYB for different mm.

InputThe first line contains an integer nn (1≤n≤104)(1≤n≤104), the number of titles ZYB has.

The ii-th of the next nn lines contains a nonempty string titi, which only contains lower case letters 'a'-'z''a'-'z', representing the ii-th title. The sum of lengths of all titles does not exceed 3×1053×105.

Then follows a line with nn integers hihi (1≤hi≤106)(1≤hi≤106), the happiness value of ii-th title.

The next line is a single integer QQ (1≤Q≤3×105)(1≤Q≤3×105), the number of queries.

For the next QQ lines, each contains a single integer mm (1≤m≤106)(1≤m≤106), meaning that you can say no more than mm letters to ZYB.

The input data contains only one test case.OutputFor each query, display a single line of integer, representing the answer. It can be proved that the answer can be uniquely written as p/qp/q where pp and qq are non-negative integers with gcd(p,q)=gcd(q,109+7)=1gcd(p,q)=gcd(q,109+7)=1, and you should display p⋅q−1mod(109+7)p⋅q−1mod(109+7), where q−1q−1 means the multiplicative inverse of qq modulo 109+7109+7.Sample Input

2
zybnb
ybyb
3 5
4
1
2
3
4

Sample Output

769230776
425925929
891125950
633120399

Hint

For the first query, you can bring him 3 happiness points if you say "z" or "n", and 15 happiness points if you say "y" or "b"; all other strings of length 1 bring no
happiness point to ZYB. Therefore, the expectation is (2×3+2×15)/26 = 18/13, and the answer is 18×13^(-1) mod (10^9+7) = 769230776.


题意:

给你n个字符串,然后每个字符串有一个快乐值。然后给你m个询问,每个询问给你一个长度,让你写出一个不大于这个长度的字串。这个字串的权值定义为,如果这个字符串中出现过第i个给定字符串的子串,那么权值乘以第i个字符串的快乐值,最后答案就是多个快乐值相乘。现在问你给定长度的字符串权值的期望。

思路:

由于要用到多个字符串的所有子串,所以我们很容易想到广义SAM.对于一个长度m,那么它的贡献为长度1~m所有子串的贡献和,考虑它的分母就是26,262,263...26m 的和,我们可以预处理出来。考虑它的分子就是后缀自动机上面所有出现的长度小于等于m的子串的贡献和。在后缀自动机中的parent树中,如果p所代表的子串出现的话,那么fa[p]所代表的的子串一定出现,那么len[fa[p]]+1~len[p]的长度都会出现,而且贡献为len[p]的贡献,根据right数组的定义,parent的出现次数要比x多,那么长度介于最长后缀和本身长度之间的后缀的出现次数肯定与x的出现次数相同。如果不同,那么parent肯定会指向第一个不相同的后缀对应的节点。所以说这从parent的长度加一到x的长度,这一整段的贡献我们都要计算上去。我们用一个前缀和数组sum,记录对应长度的贡献。对应的,区间 [len[fa[x]]+1,len[x]] 上的贡献都是y,表现在sum上面就是两个端点一加一减。统计完毕后,对sum求一遍前缀和,之后sum[i]表示所有长度为i的串的贡献。然后再次对sum求一次前缀和,这样的话sum[i]就表示所有长度为1~i的串的贡献。

 

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
typedef long long ll;
const int maxn=1e6+;
int pw[maxn],n,m;
int flag[maxn],h[maxn],sum[maxn],ans[maxn];
string s[maxn];
bool vis[maxn];
int qpow(int a,int b)
{
int ans=;
while(b)
{
if(b&)ans=(ll)ans*a%mod;
a=(ll)a*a%mod; b>>=;
}
return ans;
}
void Init()
{
pw[]=;
for(int i=;i<maxn;i++)
pw[i]=(ll)pw[i-]*26ll%mod;
for(int i=;i<maxn;i++)
pw[i]=(pw[i]+pw[i-])%mod;
}
struct SAM{
int fa[maxn<<],l[maxn<<],nxt[maxn<<][];
int last,tot;
void Init()
{
last=tot=;
memset(nxt[tot],,sizeof nxt[tot]);
l[tot]=fa[tot]=;
}
int NewNode()
{
++tot;
memset(nxt[tot],,sizeof nxt[tot]);
l[tot]=fa[tot]=;
return tot;
}
void Insert(int ch)
{
int p,q,np,nq;
if(nxt[last][ch])
{
p=last;q=nxt[p][ch];
if(l[q]==l[p]+) last=q;//////
else
{
nq=NewNode();
l[nq]=l[p]+;fa[nq]=fa[q];
memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
fa[q]=nq;
while(p&&nxt[p][ch]==q) nxt[p][ch]=nq,p=fa[p];
last=nq;//////
}
}
else
{
np=NewNode(),p=last;
last=np; l[np]=l[p]+;
while(p&&!nxt[p][ch]) nxt[p][ch]=np,p=fa[p];
if(!p) fa[np]=;
else
{
q=nxt[p][ch];
if(l[q]==l[p]+) fa[np]=q;
else
{
nq=NewNode();
memcpy(nxt[nq],nxt[q],sizeof nxt[q]);
fa[nq]=fa[q];
l[nq]=l[p]+;
fa[q]=fa[np]=nq;
while(p&&nxt[p][ch]==q) nxt[p][ch]=nq,p=fa[p];
}
}
}
}
void cal(string s,int val,int tag)
{
int cur=;
for(int i=;s[i];i++)
{
cur=nxt[cur][s[i]-'a'];
for(int tmp=cur;tmp&&flag[tmp]!=tag;tmp=fa[tmp])
ans[tmp]=1LL*ans[tmp]*val%mod,flag[tmp]=tag;
}
}
void build(int cur)
{
vis[cur]=;
sum[l[fa[cur]]+]=(sum[l[fa[cur]]+]+ans[cur])%mod;
sum[l[cur]+]=(sum[l[cur]+]-ans[cur]+mod)%mod;
for(int i=;i<;i++)
{
int Nxt=nxt[cur][i];
if(Nxt&&!vis[Nxt]) build(Nxt);
}
}
} sam;
int main()
{
ios::sync_with_stdio();
cin.tie(); cout.tie();
Init(); sam.Init();
cin>>n;
for(int i=;i<=n;++i)
{
cin>>s[i]; sam.last=;
for(int j=;s[i][j];++j)
sam.Insert(s[i][j]-'a');
}
fill(ans,ans+maxn,);
for(int i=;i<=n;++i) cin>>h[i];
for(int i=;i<=n;++i) sam.cal(s[i],h[i],i);
sam.build(); sum[]=;
for(int i=;i<maxn;++i) sum[i]=(sum[i]+sum[i-])%mod;
for(int i=;i<maxn;++i) sum[i]=(sum[i]+sum[i-])%mod;
cin>>m;
while(m--)
{
int k; cin>>k;
cout<<1LL*sum[k]*qpow(pw[k],mod-)%mod<<endl;
}
return ;
}
												

HDU 6405 Make ZYB Happy(广义SAM)的更多相关文章

  1. 【HDU 4436】 str2int (广义SAM)

    str2int Problem Description In this problem, you are given several strings that contain only digits ...

  2. hdu6405Make ZYB Happy 广义sam

    题意:给出n(n<=10000)个字符串S[1~n],每个S[i]有权值val[i],随机等概率造一个由小写字母构成的字符串T,Sum = 所有含有子串T的S[i]的val[i]之积,求Sum的 ...

  3. 【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 974  Solved: 573 Descriptio ...

  4. 【BZOJ 3473】 字符串 (后缀数组+RMQ+二分 | 广义SAM)

    3473: 字符串 Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串 ...

  5. luogu3346 诸神眷顾的幻想乡 (广义SAM)

    首先,让每一个叶节点做一次树根的话,每个路径一定至少有一次会变成直上直下的 于是对于每个叶节点作为根产生的20个trie树,把它们建到同一个广义SAM里 建法是对每个trie dfs去建,last就是 ...

  6. loj#6031. 「雅礼集训 2017 Day1」字符串(SAM 广义SAM 数据分治)

    题意 链接 Sol \(10^5\)次询问每次询问\(10^5\)个区间..这种题第一感觉就是根号/数据分治的模型. \(K\)是个定值这个很关键. 考虑\(K\)比较小的情况,可以直接暴力建SAM, ...

  7. Luogu P3181 [HAOI2016]找相同字符 广义$SAM$

    题目链接 \(Click\) \(Here\) 设一个串\(s\)在\(A\)中出现\(cnt[s][1]\)次,在\(B\)中出现\(cnt[s][2]\)次,我们要求的就是: \[\sum cnt ...

  8. CF666E Forensic Examination 广义SAM、线段树合并、倍增、扫描线

    传送门 朴素想法:对\(M\)个匹配串\(T_1,...,T_M\)建立广义SAM,对于每一次询问,找到这个SAM上\(S[pl...pr]\)对应的状态,然后计算出对于每一个\(i \in [l,r ...

  9. Luogu4022 CTSC2012 熟悉的文章 广义SAM、二分答案、单调队列

    传送门 先将所有模板串扔进广义SAM.发现作文的\(L0\)具有单调性,即\(L0\)更小不会影响答案,所以二分答案. 假设当前二分的值为\(mid\),将当前的作文放到广义SAM上匹配. 设对于第\ ...

随机推荐

  1. 护网杯web

    首先进入网页后,观察到有sign up 点击sign up 进行注册 再点击sign in 进行登录 进入一个买辣条的界面,可以知道,5元可以买一包大辣条,多包大辣条可以换一包辣条之王,多包辣条之王可 ...

  2. ThinkPHP v5.1.x POP 链分析

    环境:MacOS 10.13 MAMAP Prophp 7.0.33 + xdebugVisual Studio Code前言我所理解的 POP Chain:利用魔术方法并巧妙构造特殊属性调用一系列函 ...

  3. python:0

    if __name__ == '__main__': r = Rectangle() 79 def __str__(self): 80 return "address:(%d, %d)&qu ...

  4. 转:MySQL中变量的定义和变量的赋值使用(转)

    MySQL中变量的定义和变量的赋值使用(转)   说明:现在市面上定义变量的教程和书籍基本都放在存储过程上说明,但是存储过程上变量只能作用于begin...end块中,而普通的变量定义和使用都说的比较 ...

  5. useReducer代替Redux

    创建state.js import React, { createContext,useContext,useReducer } from 'react'; export const countTex ...

  6. requirements.txt的创建及使用

    python的包管理 pip方式: 创建 (venv) $ pip freeze >requirements.txt 执行 (venv) $ pip install -r requirement ...

  7. Win 使用终端创建mysql数据库及使用(5)

    删除你创建过的数据库newsql里面的所有表 这里必须安装了mysql,并且知道用户名密码IP地址.因为我用的window,所以只介绍Win使用cmd创建的方式 首先windown+R 出现窗口输入c ...

  8. HDFS之NameNode

    NameNode&Secondary NameNode工作机制 1)第一阶段:namenode启动 (1)第一次启动namenode格式化后,创建fsimage和edits文件.如果不是第一次 ...

  9. python分支循环

    1.遍历循环 for i in range(5) for i in range (M,N,K) for c in s: for c in 'python' print(c,end="&quo ...

  10. win到linux的编码问题

    从windows到linux的文件可能存在编码问题时,这是因为,Linux和Windows文本文件的行结束标志不同.在Linux中,文本文件用"\n"表示回车换行,而Windows ...