考虑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自动机 概率期望 高斯消元的更多相关文章

  1. 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 ...

  2. 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元

    [BZOJ4820][Sdoi2017]硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬 ...

  3. hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】

    含高斯消元模板 2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2 ...

  4. [HNOI2011]XOR和路径 概率期望 高斯消元

    题面 题解:因为异或不太好处理,,,因此按位来算,这样最后的答案就是每一位上的值乘对应的权值再求和.本着期望要倒退的原则,,,我们设$f[i]$表示从$i$到$n$,xor和为1的概率.那么观察$xo ...

  5. BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)

    容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...

  6. bzoj 1444 AC自动机 + 矩阵乘法 | 高斯消元

    恶补了一下AC自动机,花了一天时间终于全部搞明白了. 思路:将每个人的串加入AC自动机,在AC自动机生成的状态图上建边,注意单词末尾的节点只能转移到自己概率为1, 然后将矩阵自乘几十次后误差就很小了, ...

  7. BZOJ.3143.[HNOI2013]游走(概率 期望 高斯消元)

    题目链接 参考 远航之曲 把走每条边的概率乘上分配的标号就是它的期望,所以我们肯定是把大的编号分配给走的概率最低的边. 我们只要计算出经过所有点的概率,就可以得出经过一条边(\(u->v\))的 ...

  8. luoguP4457 [BJOI2018]治疗之雨 概率期望 + 高斯消元

    应该是最后一道紫色的概率了....然而颜色啥也代表不了.... 首先看懂题意: 你现在有$p$点体力,你的体力上限为$n$ 在一轮中, 1.如果你的体力没有满,你有$\frac{1}{m + 1}$的 ...

  9. [HNOI2013] 游走 - 概率期望,高斯消元,贪心

    假如我们知道了每条边经过的期望次数,则变成了一个显然的贪心.现在考虑如何求期望次数. 由于走到每个点后各向等概率,很显然一条边的期望次数可以与它的两个端点的期望次数,转化为求点的期望次数 考虑每个点对 ...

随机推荐

  1. 利用FlubuCore用C#来写持续集成和持续部署脚本

    前言 随着近些年微服务的流行,有越来越多的开发者和团队所采纳和使用,它的确提供了很多的优势也解决了很多的问题,但是我们也知道也并不是银弹,提供优势的同时它也给我们的开发人员和团队也带来了很多的挑战. ...

  2. 线性动归之Wooden Sticks

    题面:现在有n(n<5000)个木头,每个木头都有长度l和重量w(l<10000,w<10000),现在你要对木头进行加工: 1.第一根木头需要先花费1min: 2.加工完第i跟木头 ...

  3. Mysql如何取当日的数据

    下面的sql语句可以取出当日的数据 SELECT * FROM table WHERE 时间字段 BETWEEN DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00') AND ...

  4. Java入门系列之final

    前言 在C#经典面试中掺杂过Java的final关键字,主要用于类不能被继承,在C#则是利用关键字seal修饰类为密封类,而在Java中的final关键字的具体用法包含C#中const.readonl ...

  5. Linux多任务编程之六:编写多进程程序及其代码(转)

    来源:CSDN  作者:王文松  转自Linux公社 ------------------------------------------------------------------------- ...

  6. 简单shellcode学习

    本文由“合天智汇”公众号首发 作者:hope 引言 之前遇到没开启NX保护的时候,都是直接用pwtools库里的shellcode一把梭,也不太懂shellcode代码具体做了些什么,遇到了几道不能一 ...

  7. Python 图像处理 OpenCV (14):图像金字塔

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  8. 接口测试框架实战(三)| JSON 请求与响应断言

    关注公众号,获取测试开发实战干货合辑.本文节选自霍格沃兹<测试开发实战进阶>课程教学内容. 数据驱动就是通过数据的改变驱动自动化测试的执行,最终引起测试结果的改变.简单来说,就是参数化在自 ...

  9. elementui 使用Form表单 的 resetForm表单功能出现的问题

    代码因为在保密机上,这里只进行描述并截取elemen文档中的代码作为参考 今天在开发一个很简单需求的时候遇到的问题,在使用elementui的表单功能,将增和改的表单进行了复用,是在表单的父组件 dr ...

  10. 2.5万字长文简单总结SpringMVC请求参数接收

    这是公众号<Throwable文摘>发布的第22篇原创文章,暂时收录于专辑<架构与实战>.暂定下一篇发布的长文是<图文分析JUC同步器框架>,下一篇发布的短文是&l ...