HDU 6405 Make ZYB Happy(广义SAM)
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)的更多相关文章
- 【HDU 4436】 str2int (广义SAM)
str2int Problem Description In this problem, you are given several strings that contain only digits ...
- hdu6405Make ZYB Happy 广义sam
题意:给出n(n<=10000)个字符串S[1~n],每个S[i]有权值val[i],随机等概率造一个由小写字母构成的字符串T,Sum = 所有含有子串T的S[i]的val[i]之积,求Sum的 ...
- 【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 974 Solved: 573 Descriptio ...
- 【BZOJ 3473】 字符串 (后缀数组+RMQ+二分 | 广义SAM)
3473: 字符串 Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串 ...
- luogu3346 诸神眷顾的幻想乡 (广义SAM)
首先,让每一个叶节点做一次树根的话,每个路径一定至少有一次会变成直上直下的 于是对于每个叶节点作为根产生的20个trie树,把它们建到同一个广义SAM里 建法是对每个trie dfs去建,last就是 ...
- loj#6031. 「雅礼集训 2017 Day1」字符串(SAM 广义SAM 数据分治)
题意 链接 Sol \(10^5\)次询问每次询问\(10^5\)个区间..这种题第一感觉就是根号/数据分治的模型. \(K\)是个定值这个很关键. 考虑\(K\)比较小的情况,可以直接暴力建SAM, ...
- Luogu P3181 [HAOI2016]找相同字符 广义$SAM$
题目链接 \(Click\) \(Here\) 设一个串\(s\)在\(A\)中出现\(cnt[s][1]\)次,在\(B\)中出现\(cnt[s][2]\)次,我们要求的就是: \[\sum cnt ...
- CF666E Forensic Examination 广义SAM、线段树合并、倍增、扫描线
传送门 朴素想法:对\(M\)个匹配串\(T_1,...,T_M\)建立广义SAM,对于每一次询问,找到这个SAM上\(S[pl...pr]\)对应的状态,然后计算出对于每一个\(i \in [l,r ...
- Luogu4022 CTSC2012 熟悉的文章 广义SAM、二分答案、单调队列
传送门 先将所有模板串扔进广义SAM.发现作文的\(L0\)具有单调性,即\(L0\)更小不会影响答案,所以二分答案. 假设当前二分的值为\(mid\),将当前的作文放到广义SAM上匹配. 设对于第\ ...
随机推荐
- Python3.7.1学习(一):redis的连接和简单使用
1.python 利用 redis 第三方库 首先安装:pip install redis 2.reids的连接 Redis使用StrictRedis对象来管理对一个redis server 的所有连 ...
- 【Vue | ElementUI】Vue离开当前页面时弹出确认框实现
Vue离开当前页面时弹出确认框实现 1. 实现目的 在某种业务场景下,用户不允许跳转到其他页面.于是,需要在用户误操作或者是点击浏览器跳转时提示用户. 2. 实现原理 使用路由守卫beforeRout ...
- django_4:数据库1——django操作数据库
创建数据库记录(插入) 使用python3 manage.py shell(python3亲测好使) ipython3 manage.py shell(亲测不好使) 方式一. [root@centos ...
- 【原创】(十一)Linux内存管理slub分配器
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- python gui tkinter快速入门教程 | python tkinter tutorial
本文首发于个人博客https://kezunlin.me/post/d5c57f56/,欢迎阅读最新内容! python tkinter tutorial Guide main ui messageb ...
- PHP中echo与print语句的实例教程
在 PHP 中,有两种基本的输出方法:echo 和 print. echo与print的差异 echo能够输出一个以上的字符串. print只能输出一个字符串,并始终返回 1. 提示:echo 比 p ...
- linux网络配置(ifcfg)
将linux主机接入到网络需要配置哪些配置项? IP/NETMASK:本地通信. 路由(网管):跨网络通信. DNS服务器地址:基于主机名通信. DNS服务器有三种:主/备用DNS服务器/第三备份dn ...
- webuploader 快速应用(C#)
百度的WebUploader前端插件作为目前比较好用且免费的附件上传工具,利用了断点续传特点实现了大文件上传功能,其更好的兼容性与界面效果完全可以替换掉IE的activex 上传控件.许多人或许还不知 ...
- csrf与xss
CSRF攻击攻击原理及过程如下: 1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A: 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登 ...
- Linux01机和Linux02机的切换 和秘钥的配置
先试一下 01机和02机是否可以切换成功 使用 ssh root@ip地址 输入密码 ifconfig查看ip是否正确 切换回01机 01机配置的秘钥 查看隐形文件 01机配置秘钥 输入 ssh-c ...