**

为这场多校的出题人点赞,题目很有趣!!!,质量很高

**

Make ZYB Happy

Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 43 Accepted Submission(s): 22

Problem Description
It’s known to all that ZYB is godlike, so obviously he has a large number of titles, such as jsking, bijingzyb and nbazyb. ZYB likes his titles very much.

Each of ZYB’s titles is a string consisting of lower case letters ‘a’-‘z’ associated with a happiness value hi, which shows how much ZYB likes this title. If you say any substring of some title with happiness value x, he will get x 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: zybnb (with happiness value 3) and ybyb (with happiness value 5). If you say y, b or yb, ZYB will get 15 happiness points; if you say z, zy or zyb, ZYB will only get 3 happiness points; if you say ybz or ybac 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 m 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 m and only containing ‘a’-‘z’ with equal probability. You want to know the expectations of happiness points you will bring to ZYB for different m.

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

The i-th of the next n lines contains a nonempty string ti, which only contains lower case letters ‘a’-‘z’, representing the i-th title. The sum of lengths of all titles does not exceed 3×105.

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

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

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

The input data contains only one test case.

Output
For each query, display a single line of integer, representing the answer. It can be proved that the answer can be uniquely written as p/q where p and q are non-negative integers with gcd(p,q)=gcd(q,109+7)=1, and you should display p⋅q−1mod(109+7), where q−1 means the multiplicative inverse of q modulo 109+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个字符串。 每个字符串有一个权值val[i]
现在可以构造出一种串,其收获为给出的N个字符串中合法串的权值乘积之和。
如果一个串的子串集合包含构造出来的串,则称这个串合法。
现在给出一个数m,要你求出随机构造一个长度小于等于m的串的收获期望。

解题思路:
本质问题就是分别求不同子串个数,不过这个问题给出了N个串,每个串还都有自己的权值。
直接暴力去求那是N^2的复杂度,显然是无法接受的。
考虑如何化简状态。
后缀自动机就是处理这种问题的非常优秀的算法。
没学过后缀自动机的同学请移步
hihocode 业界良心,讲得非常详细。
先考虑N=1 的情况。
用后缀自动机处理出所有状态,然后再沿着路径dfs一遍,求出每个状态对答案的贡献。
不过要注意的是,这里用的是状态转移路径,而不是后缀链接路径。
状态转移路径是一个有向无环图,所以直接dfs暴力求出每个状态对每种长度的贡献复杂度会是O(N^2)级别的(md,一开始没想清楚这里,这里被坑了两个小时)
考虑到后缀自动机的每个状态包含的子串是连续的后缀,所以,可以使用前缀和的思想进行优化。这样,复杂度就降到了O(N) 。已经非常优秀了。

再考虑N>1 的情况。
emmmmm,没什么好考虑的了,跟N=1的做法一模一样,直接在原来的后缀自动机上添加新的串(也就是所谓的广义后缀自动机),
然后一样dfs求一下贡献就好。

然后就可以直接预处理出所有答案,查询的时候直接输出结果即可。

感觉用前缀和优化复杂度的技巧非常巧妙。 学习了。

#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=a-1;i>=b;--i)
#define fuck(x) cout<<'['<<#x<<' '<<(x)<<']'
#define FIN freopen("in.txt","r",stdin);
using namespace std;
#define N 1000050
typedef long long LL;
char s[N];
int ch[N][27],len[N],link[N],rd[N],last,tot,rt,n;
int F[N],ans[N];
int cnt[N];
void add(char pos) {int x = pos - 'a' + 1, p = last, np = ++tot;last = np;len[np] = len[p] + 1;F[np] = 1LL;while (p && !ch[p][x]) ch[p][x] = np, p = link[p];if (!p)link[np] = rt;else {int q = ch[p][x];if (len[q] == len[p] + 1)link[np] = q;else {int nq = ++tot;len[nq] = len[p] + 1;memcpy(ch[nq],ch[q],sizeof(ch[q]));link[nq] = link[q];link[q] = link[np] = nq;while (p && ch[p][x] == q) ch[p][x] = nq, p = link[p];}}return ;
}
void init() {rt = last = ++tot;
}
//<------------SAM 结束----------------->
const int MOD = 1e9+7;
const int MAX = 1e4+10;
int vis[N];
string  str[N];
long long val[N];
long long sval[N];
long long QANS[N];
long long base[N];
void presolve(string &S,int id,long long V) {int len = S.size();int now = rt;for(int i=0; i<len; i++) {char nowc=S[i]-'a'+1;now = ch[now][nowc];int temp = now;while(temp!=1 && vis[temp]!=id) {vis[temp] = id;val[temp] = val[temp] * V%MOD ;val[temp] %= MOD;temp = link[temp];}}
}
bool nodevis[N];
// 利用前缀和思想是O(N) 否则 直接遍历是N^2 的复杂度。
void dfs(int u){QANS[len[link[u]]+1] = (QANS[len[link[u]]+1]+val[u])%MOD;QANS[len[u]+1] = (QANS[len[u]+1]-val[u]+MOD)%MOD;nodevis[u]=1;for(int i=1;i<=26;i++){if(ch[u][i] && nodevis[ch[u][i]]==0){dfs(ch[u][i]);}}
}
LL quickpow(LL a,LL b){LL ans=1;while(b){if(b&1){ans=(ans*a)%MOD;}a=(a*a)%MOD;b>>=1;}return ans;
}
int main() {//cout<<"yes"<<endl;base[0]=1;for(int i=1;i<=N;i++){base[i]=26ll*base[i-1];base[i]%=MOD;}for(int i=2;i<=N;i++){base[i]+=base[i-1];base[i]%=MOD;}init();ios::sync_with_stdio(false);cin>>n;for(int i=0; i<n; i++) {cin>>str[i];int len = str[i].size();for(int j= 0; j<len; j++) {add(str[i][j]);}last=rt;}for(int i=1;i<=tot;i++){val[i]=1;}for(int i=0;i<n;i++){cin>>sval[i];presolve(str[i],i+1,sval[i]);}val[0]=val[1]=0;dfs(rt);//cout<<"yes"<<endl;for(int i=1;i<=N-5;i++){QANS[i]+=QANS[i-1];QANS[i]%=MOD;}for(int i=1;i<=N-5;i++){QANS[i]+=QANS[i-1];QANS[i]%=MOD;}for(int i=1;i<=N/2 ;i++){QANS[i]=QANS[i]*quickpow(base[i],MOD-2)%MOD;}int Q;cin>>Q;int cnts;while(Q--){cin>>cnts;//cout<<base[cnts]<<endl;//cout<<quickpow(base[cnts],MOD-2)<<" "<<QANS[cnts]<<endl;cout<<QANS[cnts]<<endl;}return 0;
}

HDU 6405 Make ZYB Happy 后缀自动机 前缀和优化相关推荐

  1. 序列计数(动态规划/自动机/前缀和优化)

    序列计数 对于一个小写字母的序列每次可以将相邻两个不同的小写字母都变为二者之一,可以进行无限次这样的操作,求解可以产生多少种不同的序列. 首先我们不能考虑操作,而是考虑合法序列,显然最后会形成若干个区 ...

  2. HDU - 7091 重叠的子串(后缀自动机+set启发式合并+树上倍增)

    题目链接:点击查看 题目大意:给定一个只含小写字母的字符串 sss 和 qqq 次询问,每次询问给定一个字符串,以 s[l..r]s[l..r]s[l..r] 的形式给出,判断 sss 中是否存在两个 ...

  3. HDU多校4 - 6988 Display Substring(后缀自动机+二分)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串 sss,每个字母都有一个权值,现在要求所有本质不同子串中权值和第 kkk 大的权值 题目分析:如果没有本质不同,那有一个很简单的二分套二 ...

  4. 美团杯2020 - 半前缀计数(后缀自动机)

    题目链接:点击查看 题目大意: 蒜斜刚来PKU的时候还不知道有"北大算协"这个社团,因此他总是觉得周围的人在偷偷议论着他,比如说: "算协(注:非蒜斜)举办的活动好有趣啊 ...

  5. hdu 6194string string string 后缀自动机

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6194 查询原串中出现次数等于k次的子串数量.需要用到基数排序. 构造完后缀自动机之后将节点按照maxl ...

  6. HDU 4416 (后缀自动机)

    HDU 4416 Good Article Good sentence Problem : 给一个串S,和一些串T,询问S中有多少个子串没有在T中出现. Solution :首先对所有的T串建立后缀自 ...

  7. HDU 3518 HDU 4416【后缀自动机len的使用】

    max:即代码中 len 变量,它表示该状态能够接受的最长的字符串长度. min:表示该状态能够接受的最短的字符串长度.实际上等于该状态的 fail 指针指向的结点的 len + 1. max-min ...

  8. HDU - 4416 Good Article Good sentence(广义后缀自动机/后缀自动机)

    题目链接:点击查看 题目大意:给出一个字符串 s ,再给出 n 个字符串 t ,现在问字符串 s 中有多少个不同的子串满足不是 t1 ~ tn 中任意一个字符串的子串 题目分析:第一次接触这样的题目, ...

  9. HDU - 4641 K-string(后缀自动机)

    题目链接:点击查看 题目大意:给出一个字符串 s ,规定 K-string 为字符串 s 中出现次数大于等于 k 次的字串,现在有 m 次操作,每次操作有两种: 1 ch:在字符串 s 后面添加字符 ...

  10. HDU 6194 后缀自动机

    后缀自动机求K次出现的子串的个数: #include <iostream> #include<cstdio> #include<algorithm> #includ ...

最新文章

  1. 【动态规划】最长公共子序列与最长公共子串
  2. RobotFramework下的http接口自动化Set Request Body 关键字的使用
  3. “禁止大数据杀熟”拟入法!个性化推荐功能也应提供拒绝选项
  4. 2013秋浙大远程教育计算机应用基础-9计算机多媒体技术,2013秋浙大远程教育计算机应用基础-9...
  5. 应用服务器——jetty架构分析
  6. 对象反序列化出现类型不匹配的情况(spring-boot-devtools)
  7. 格雷码 matlab,基于格雷码的结构光重建代码(MATLAB版本)
  8. python爬虫 django搜索修改更新数据_python应用:Django中更新多个对象数据与删除对象的方法...
  9. 如果华为自研的芯片无法给华为手机带来更高的性价比,那么华为自研芯片给消费者带来的意义是什么呢?
  10. Android已读未读功能,Android实现小圆点显示未读功能
  11. DXperience 6.3.9 for Visual Studio 2002, 2003
  12. OSChina 周三乱弹 —— 生活要懂得苦中作乐
  13. Android改包1
  14. python怎么安装requests包_python怎么安装requests库
  15. vue 使用flowplayer_Flowplayer视频播放插件
  16. CPAN下载安装pm包方法
  17. 下载tomcat最新版本
  18. 利用JavaScript制作倒计时牌(转)
  19. Tableau各版本更新情况
  20. 如何向外行解释,Bug是如何产生的?

热门文章

  1. 发个贴,舒缓下自己焦虑的心情
  2. Calc3: Partial Derivative
  3. PDF Expert快捷键
  4. HTML5定稿,为什么是原生App的颠覆
  5. CTGU实验6_2-创建函数计算图书超期天数
  6. 非负数的正则表达式匹配
  7. qt开源项目: tiled 瓦片 游戏地图编辑器
  8. 2019信息素养知识点
  9. membase数据库_Meta分析之文献检索步骤
  10. [转]漫谈个人知识管理-PKM的方法