4.23 子串 AC自动机 概率期望 高斯消元


考虑40分。
设出状态 f[i]表示匹配到了i位还有多少期望长度能停止。可以发现这个状态有环 需要高斯消元。
提供一种比较简单的方法:由于期望的线性可加性 可以设状态f[i]表示由匹配到i到匹配到i+1需要的期望长度。
需要预处理前缀和和KMP的nex数组来辅助转移。
if(n==1)
{
gc(a);
len=strlen(a+1);
ll j=0;
memset(nex,0,sizeof(nex));
rep(2,len,i)
{
while(j&&a[i]!=a[j+1])j=nex[j];
if(a[i]==a[j+1])++j;
nex[i]=j;
}
rep(0,len-1,i)
{
f[i]=1;
for(ll j=0;j<=25;++j)
{
if(a[i+1]-'a'!=j)
{
ll w=i;
while(w&&a[w+1]-'a'!=j)w=nex[w];
if(a[w+1]-'a'!=j){if(i)f[i]=(f[i]+sum[i-1])%mod;}
else f[i]=(f[i]+sum[i-1]-sum[w])%mod;
++f[i];
}
}
if(i>=1)sum[i]=(sum[i-1]+f[i])%mod;
else sum[i]=f[i];
}
ll ans=0;
rep(0,len-1,i)ans=(ans+f[i])%mod;
putl(ans);
}
考虑正解。
容易想到建立出AC自动机 在trie图上跑。
易设状态f[i]表示到达i这个点的期望长度。
遗憾的是 这个玩意根本不能转移。或者说转移必然存在问题 比如 \(f_i=\sum_{v\in fa[i],vis[v]\neq 1}\frac{f_v+1}{26}\)
vis数组表示v是否是终止节点。
容易想错的是 v转移到i的概率确实是1/26 但是i从v处转移的概率却不一定是1/26.
可能到达v的次数有很多次 每次概率都是1/26不过这个次数并没有被统计到 这是关键点。
而且据EI dalao所说 v转移到i的所有的概率和不为1 而且 E[x/y] 通常不等于 E[x]/E[y]。
总之 当做概率出现的问题吧.
考虑由最开始的状态倒推期望 设f[i]表示到达i这个节点还需要多少长度才能停止。
容易 发现转移 \(f_i=1+\sum_{v\in son[i]}\frac{f_v}{26}\)
可以发现这个状态的转移概率确实1/26.
而且这个状态带环。所以高斯消元即可。
const ll MAXN=12,maxn=210;
ll T,n,len,cnt;
inline ll ksm(ll b,ll p){ll cnt=1;while(p){if(p&1)cnt=(ll)cnt*b%mod;b=(ll)b*b%mod;p=p>>1;}return cnt;}
char a[maxn];
ll nex[maxn],q[maxn];
ll b[maxn][maxn];
ll f[maxn],sum[maxn];//f[i]表示由长度i到长度i+1的期望.
struct AC
{
ll s;
ll fail;
ll ch[26];
}t[maxn];
inline ll get_new()
{
++cnt;
t[cnt]=t[200];
return cnt;
}
inline void insert(char *a)
{
ll p=0;
ll len=strlen(a+1);
rep(1,len,i)
{
ll w=a[i]-'a';
if(!t[p].ch[w])t[p].ch[w]=get_new();
p=t[p].ch[w];
}
t[p].s=1;
}
inline void get_fail()
{
ll l=0,r=0;
rep(0,25,i)if(t[0].ch[i])q[++r]=t[0].ch[i];
while(++l<=r)
{
ll x=q[l];
rep(0,25,i)
{
ll tn=t[x].ch[i];
if(tn)fail(tn)=t[fail(x)].ch[i],q[++r]=tn;
else t[x].ch[i]=t[fail(x)].ch[i];
}
}
rep(1,r,i)t[q[i]].s|=t[fail(q[i])].s;
}
inline void GAUSS()
{
rep(0,cnt,i)
{
ll p=i;
rep(i+1,cnt,j)if(abs(b[j][i])>abs(b[i][i]))p=j;
if(p!=i){rep(0,cnt,k)swap(b[i][k],b[p][k]);swap(f[i],f[p]);}
ll d=ksm(b[i][i],mod-2);
rep(0,cnt,j)
{
if(i==j)continue;
ll ww=d*b[j][i]%mod;
rep(0,cnt,k)b[j][k]=(b[j][k]-b[i][k]*ww)%mod;
f[j]=(f[j]-f[i]*ww)%mod;
}
}
rep(0,cnt,i)f[i]=f[i]*ksm(b[i][i],mod-2)%mod;
}
signed main()
{
freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
//freopen("substring.in","r",stdin);
//freopen("substring.out","w",stdout);
gt(T);
while(T--)
{
gt(n);
{
cnt=0;t[0]=t[200];
rep(1,n,i)gc(a),insert(a);
get_fail();
//构建矩阵.
ll ww=ksm(26,mod-2);
memset(f,0,sizeof(f));
memset(b,0,sizeof(b));
rep(0,cnt,i)
{
b[i][i]=1;
if(t[i].s)continue;
rep(0,25,j)
{
int tn=t[i].ch[j];
b[i][tn]=(b[i][tn]-ww)%mod;
}
++f[i];
}
/*rep(0,cnt,i)
{
rep(0,cnt,j)cout<<(b[i][j]+mod)%mod<<' ';
cout<<f[i]<<endl;
}*/
GAUSS();
/*rep(0,cnt,i)
{
rep(0,cnt,j)cout<<b[i][j]<<' ';
cout<<f[i]<<endl;
}*/
//ll ans=0;
//rep(1,cnt,i)if(t[i].s)ans=(ans+f[i])%mod;
//rep(0,cnt,i)putl((f[i]+mod)%mod);
putl((f[0]+mod)%mod);
}
}
return 0;
}
4.23 子串 AC自动机 概率期望 高斯消元的更多相关文章
- 2016ACM/ICPC亚洲区沈阳站H - Guessing the Dice Roll HDU - 5955 ac自动机+概率dp+高斯消元
http://acm.hdu.edu.cn/showproblem.php?pid=5955 题意:给你长度为l的n组数,每个数1-6,每次扔色子,问你每个串第一次被匹配的概率是多少 题解:先建成ac ...
- 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元
[BZOJ4820][Sdoi2017]硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬 ...
- hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】
含高斯消元模板 2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2 ...
- [HNOI2011]XOR和路径 概率期望 高斯消元
题面 题解:因为异或不太好处理,,,因此按位来算,这样最后的答案就是每一位上的值乘对应的权值再求和.本着期望要倒退的原则,,,我们设$f[i]$表示从$i$到$n$,xor和为1的概率.那么观察$xo ...
- BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...
- bzoj 1444 AC自动机 + 矩阵乘法 | 高斯消元
恶补了一下AC自动机,花了一天时间终于全部搞明白了. 思路:将每个人的串加入AC自动机,在AC自动机生成的状态图上建边,注意单词末尾的节点只能转移到自己概率为1, 然后将矩阵自乘几十次后误差就很小了, ...
- BZOJ.3143.[HNOI2013]游走(概率 期望 高斯消元)
题目链接 参考 远航之曲 把走每条边的概率乘上分配的标号就是它的期望,所以我们肯定是把大的编号分配给走的概率最低的边. 我们只要计算出经过所有点的概率,就可以得出经过一条边(\(u->v\))的 ...
- luoguP4457 [BJOI2018]治疗之雨 概率期望 + 高斯消元
应该是最后一道紫色的概率了....然而颜色啥也代表不了.... 首先看懂题意: 你现在有$p$点体力,你的体力上限为$n$ 在一轮中, 1.如果你的体力没有满,你有$\frac{1}{m + 1}$的 ...
- [HNOI2013] 游走 - 概率期望,高斯消元,贪心
假如我们知道了每条边经过的期望次数,则变成了一个显然的贪心.现在考虑如何求期望次数. 由于走到每个点后各向等概率,很显然一条边的期望次数可以与它的两个端点的期望次数,转化为求点的期望次数 考虑每个点对 ...
随机推荐
- PE文件格式详解(六)
0x00 前言 前面两篇讲到了输出表的内容以及涉及如何在hexWorkShop中找到输出表及输入DLL,感觉有几个地方还是没有理解好,比如由数据目录表DataDirectory[16]找到输出表表后以 ...
- Kail安装VMtools
0x00 前言 之前用吾爱的xp虚拟机,总是装不上vmtools,真是难受.每次跨机器粘贴复制都一件极其痛苦的事,而且虚拟机还不能直接浏览硬盘上的文件.虽说安全性保证了,但是这是真的痛苦.这两天开始用 ...
- WPF弹性、惯性效果应用
WPF弹性.惯性效果.已发布在了一些网站,都是这里写的 代码改编自微软示例代码库 // Copyright © Microsoft Corporation. All Rights Reserved. ...
- XSS与CSRF定义
一. CSRF 1. CSRF的基本概念 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通 ...
- Flask 基础组件(五):请求和响应
from flask import Flask from flask import request from flask import render_template from flask impor ...
- 数据可视化之PowerQuery篇(四)二维表转一维表,看这篇文章就够了
https://zhuanlan.zhihu.com/p/69187094 数据分析的源数据应该是规范的,而规范的其中一个标准就是数据源应该是一维表,它会让之后的数据分析工作变得简单高效. 在之前的文 ...
- Flex移动布局中单行和双行布局的区别以及使用
这里是单行布局 使用ul>li 来布局 <ul class="local-nav"> <li> <a ...
- .Net Core微服务入门全纪录(完结)——Ocelot与Swagger
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 前言 上一篇[.Net Core微服务入门全纪录(八)--Docker Compose与容器网络]完成了docker-compose.y ...
- Redis之对象
1.对象的类型与编码 Redis使用对象来表示数据库中的键和值,每次我们在Redis的数据库中新创建一个键值对,我们至少会创建两个对象,一个键对象,另一个值对象. 每个对象都由一个redisObjec ...
- Ethical Hacking - NETWORK PENETRATION TESTING(8)
WEP Cracking Basic case Run airdump-ng to log all traffic from the target network. airodump-ng --cha ...