我一开始想的是倒着来,发现太屎,后来想到了一种神奇的方法——我们带着一个既有期望又有概率的矩阵,偶数(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. 我是一个MySQL小白

    我是一个MySQL小白 第一回早起装扮 “mysql,Oracle,SQL-SERVER你们三个 起床没?”,清晨七点多师父喊道. “师父,我(mysql)哪敢睡觉呀,我还在查询表呢,有客户的密码忘记 ...

  2. 移植Linux Kernel SM750 驱动到VxWorks 7

    一.SM750简介 SM750 是SiliconMotion 推出的一款适合嵌入式设备的显卡(Embedded GPU),采用PCIe接口与CPU连接,内部集成16MB DDR SDRAM显存,产品具 ...

  3. Django自带后台使用配置

    参考官网地址:https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ ,本文章值是介绍简单配置,如果需要详细内容可以查阅官方文档 自动管理界 ...

  4. 笨方法学python之import sys与from sys import argv的区别

    这是在网上看到的一个大神的解答: sys is a module that contains “system functionality”. sys.argv is a list containing ...

  5. 004---基于TCP的套接字

    基于TCP的套接字 tcp是基于链接的,必须先启动服务端,然后再启动客户端去连接服务端. 之前实现的简单套接字就是基于TCP的,但是只能实现收发消息一次.服务器与客户端都断开了.不够过瘾. 通信循环版 ...

  6. PHP.37-TP框架商城应用实例-后台13-商品管理-扩展分类的添加、显示【数据分组】、搜索分类【多对多】

    商品扩展分类 需求:一件商品能有多个扩展分类,搜索任何一个分类都能搜出该商品 建表[扩展分类表] drop table if exists p39_goods_cat; create table p3 ...

  7. oracle查询优化,存储过程select表循环插入另一个表,以及索引重建

    查询语句pl/sql中用F5优化语句 ORACLE的explain plan工具的作用只有一个,获取语句的执行计划1.语句本身并不执行,ORACLE根据优化器产生理论上的执行计划2.语句的分析结果存放 ...

  8. springmvc+spring-data-jpa+hibernate环境搭建与配置

    1.JPA诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,百度百科说是JDK为了实现ORM的天下归一,目前也是在按照这个方向发展,但是还没能完全实现.在ORM框架中,Hibernate是一支 ...

  9. define 和 const常量有什么区别?

    define在预处理阶段进行替换,const常量在编译阶段使用 宏不做类型检查,仅仅进行替换,const常量有数据类型,会执行类型检查 define不能调试,const常量可以调试 define定义的 ...

  10. 【数据结构】 Queue 的简单实现

    [数据结构] Queue 的简单实现 public class XQueue<T> { /// <summary> /// 第一个元素 /// </summary> ...