我一开始想的是倒着来,发现太屎,后来想到了一种神奇的方法——我们带着一个既有期望又有概率的矩阵,偶数(2*id)代表期望,奇数(2*id+1)代表概率,初始答案矩阵一列,1的位置为1(起点为0),工具矩阵上如果是直接转移那么就是由i到j概率期望都乘上1/alphabet,特别的,对于一个包含禁忌串的节点直接由其父节点指向0,而且在计算期望是多加上他的概率,最后统计答案时把答案矩阵上所有的期望加和即可,这个方法很完美的被卡精了.......

#include <cstdio>
#include <cstring>
#include <vector>
typedef long double LD;
const int N=;
char s[];
int alpha,n,m;
struct Trie{
int ch[],fail,deep;
bool god;
}node[N];
int sz,q[N],size;
LD a[N][N],temp_a[N][N],b[N],temp_b[N],need;
inline void insert(char *w){
int p=;
for(int i=;w[i];i++){
if(node[p].ch[w[i]-'a']==)node[p].ch[w[i]-'a']=++sz,node[sz].deep=node[p].deep+;
p=node[p].ch[w[i]-'a'];
}
node[p].god=;
}
inline void build(){
q[]=;
for(int i=,j=;i<=j;i++){
for(int l=;l<alpha;l++)
if(node[q[i]].ch[l])
q[++j]=node[q[i]].ch[l],
node[q[j]].fail=q[i]?node[node[q[i]].fail].ch[l]:,
node[q[j]].god=node[q[j]].god||node[node[q[j]].fail].god;
else
node[q[i]].ch[l]=q[i]?node[node[q[i]].fail].ch[l]:;
}
}
void dfs(int x){
for(int i=;i<alpha;i++){
if(node[node[x].ch[i]].god){
a[][x<<]+=need;
a[][(x<<)+]+=need;
a[][(x<<)+]+=need;
continue;
}
a[node[x].ch[i]<<][x<<]+=need;
a[(node[x].ch[i]<<)+][(x<<)+]+=need;
if(node[node[x].ch[i]].deep>node[x].deep)
dfs(node[x].ch[i]);
}
}
inline void Multi_a(){
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
temp_a[i][j]=;
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
for(int k=;k<=size;k++)
temp_a[i][j]+=a[i][k]*a[k][j];
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
a[i][j]=temp_a[i][j];
}
inline void Multi_b(){
for(int i=;i<=size;i++)temp_b[i]=;
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
temp_b[i]+=a[i][j]*b[j];
for(int i=;i<=size;i++)b[i]=temp_b[i];
}
int main(){
scanf("%d%d%d",&n,&m,&alpha),need=./alpha;
for(int i=;i<=n;i++)
scanf("%s",s),insert(s);
build(),dfs(),size=(sz<<)+,b[]=.;
while(m){
if(m&)Multi_b();
m>>=,Multi_a();
}
LD ans=.;
for(int i=;i<=sz;i++)ans+=b[i<<];
printf("%lf",(double)ans);
return ;
}

只是错了最后一个点

然后我去接受正解,按照我们的思路我们会建出来一个概率矩阵a[i][j]表示由j转移到i的概率,那就是加上1/alphabet,当然这里也有从禁忌串直接调回0的操作,然后我们想记录答案,我们就把矩阵扩大一阶,标号为sz+1,就是记录答案,那么我们由禁忌串向sz+1加上1/alphabet,那么我们发现这个矩阵自乘多少次,他的a[sz+1][0]的答案就是我们想要的答案。

经验教训:对于矩阵乘法,答案矩阵也可以是方阵,而且在一个矩阵里意义可以不同。

#include <cstdio>
#include <cstring>
#include <vector>
typedef long double LD;
const int N=;
char s[];
int alpha,n,m;
struct Trie{
int ch[],fail,deep;
bool god;
}node[N];
int sz,q[N],size;
LD a[N][N],temp[N][N],b[N][N],need;
inline void insert(char *w){
int p=;
for(int i=;w[i];i++){
if(node[p].ch[w[i]-'a']==)node[p].ch[w[i]-'a']=++sz,node[sz].deep=node[p].deep+;
p=node[p].ch[w[i]-'a'];
}
node[p].god=;
}
inline void build(){
q[]=;
for(int i=,j=;i<=j;i++){
for(int l=;l<alpha;l++)
if(node[q[i]].ch[l])
q[++j]=node[q[i]].ch[l],
node[q[j]].fail=q[i]?node[node[q[i]].fail].ch[l]:,
node[q[j]].god=node[q[j]].god||node[node[q[j]].fail].god;
else
node[q[i]].ch[l]=q[i]?node[node[q[i]].fail].ch[l]:;
}
}
void dfs(int x){
for(int i=;i<alpha;i++){
if(node[node[x].ch[i]].god){
a[][x]+=need;
a[sz+][x]+=need;
continue;
}
a[node[x].ch[i]][x]+=need;
if(node[node[x].ch[i]].deep>node[x].deep)
dfs(node[x].ch[i]);
}
}
inline void Multi_a(){
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
temp[i][j]=;
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
for(int k=;k<=size;k++)
temp[i][j]+=a[i][k]*a[k][j];
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
a[i][j]=temp[i][j];
}
inline void Multi_b(){
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
temp[i][j]=;
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
for(int k=;k<=size;k++)
temp[i][j]+=b[i][k]*a[k][j];
for(int i=;i<=size;i++)
for(int j=;j<=size;j++)
b[i][j]=temp[i][j];
}
int main(){
scanf("%d%d%d",&n,&m,&alpha),need=(LD)./(LD)alpha;
for(int i=;i<=n;i++)
scanf("%s",s),insert(s);
build(),dfs(),size=sz+,a[size][size]=.;
for(int i=;i<=size;i++)b[i][i]=.;
while(m){
if(m&)Multi_b();
m>>=,Multi_a();
}
printf("%.6lf",(double)b[size][]);
return ;
}

AC code

【BZOJ 2553】[BeiJing2011]禁忌 AC自动机+期望概率dp的更多相关文章

  1. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  2. bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2553 题解: 利用AC自动机的dp求出所有的转移 然后将所有的转移储存到矩阵中,进行矩阵 ...

  3. bzoj 2553 [BeiJing2011]禁忌——AC自动机+概率DP+矩阵

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2553 看了题解才会…… 首先,给定一个串,最好的划分方式是按禁忌串出现的右端点排序,遇到能填 ...

  4. 【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法

    [BZOJ2553][BeiJing2011]禁忌 Description Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平. ...

  5. 【BZOJ 3811】玛里苟斯 大力观察+期望概率dp+线性基

    大力观察:I.从输出精准位数的约束来观察,一定会有猫腻,然后仔细想一想,就会发现输出的时候小数点后面不是.5就是没有 II.从最后答案小于2^63可以看出当k大于等于3的时候就可以直接搜索了 期望概率 ...

  6. BZOJ2553[BeiJing2011]禁忌——AC自动机+概率DP+矩阵乘法

    题目描述 Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi恢复了读心的能力…… 如今,在John已经成为传 ...

  7. BZOJ2553 [BeiJing2011]禁忌 AC自动机 矩阵

    原文链接http://www.cnblogs.com/zhouzhendong/p/8196279.html 题目传送门 - BZOJ2553 题意概括 引用一下lych大佬的: 在字母只有前alph ...

  8. BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )

    建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...

  9. BZOJ 3270 博物馆 && CodeForces 113D. Museum 期望概率dp 高斯消元

    大前提,把两个点的组合看成一种状态 x 两种思路 O(n^7) f[x]表示在某一个点的前提下,这个状态经过那个点的概率,用相邻的点转移状态,高斯一波就好了 O(n^6) 想象成臭气弹,这个和那个的区 ...

随机推荐

  1. phpredis命令

    <?php //redis //检查一个扩展是否已经加载.大小写不敏感. if (!function_exists('redis')) { echo '不支持 redis'; return ; ...

  2. input输入框类型

    输入大小写字母.数字.下划线: <input type="text" onkeyup="this.value=this.value.replace(/[^\w_]/ ...

  3. 转:python教程专题资源免费下载整理合集收藏

    python教程专题资源免费下载整理合集收藏 < Python学习手册(第4版)>(Learning Python, 4th Edition)[PDF] 94MB 简体中文 <Pyt ...

  4. C语言学习记录_2019.02.02

    变量在第一次被使用之前应该赋初值 scanf(“%d”,&price); scanf(“price%d %d”,&price);  scanf中的东西一定是要输入的东西. 定义常量:c ...

  5. 【Consul】Consul架构-Session会话

    Consul提供session会话机制--可以用于构建分布式锁,session可以绑定到节点.健康检查.KV数据.目的是提供颗粒锁--受 The Chubby LockService for Loos ...

  6. 3招搞定APP注册作弊

    在说如何应对之前,易盾先给各位盾友梳理移动端APP可能遇到哪些作弊风险.1. 渠道商刷量,伪造大量的下载量和装机量,但没有新用户注册:2. 对于电商.P2P.外卖等平台,会面临散户或者团队刷子的注册- ...

  7. 最火的.NET开源项目[转]

    综合类 微软企业库 微软官方出品,是为了协助开发商解决企业级应用开发过程中所面临的一系列共性的问题, 如安全(Security).日志(Logging).数据访问(Data Access).配置管理( ...

  8. Qt Demo Http 解析网址 Openssl

    今天练习了一下Qt 解析http协议,在Demo中使用到了Openssl 一上午的时间都是编译openssl,不过还是没有成功,很遗憾,这里整理了有关这个Demo的本件 网盘连接:见下方评论吧,长传太 ...

  9. 生产者与消费者-N:1-基于list

    多个生产者/一个消费者: /** * 生产者 */ public class P { private MyStack stack; public P(MyStack stack) { this.sta ...

  10. 剑指offer-二进制中1的个数11

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. class Solution: def NumberOf1(self, n): # write code here coun ...