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

    symfony可以根据数据用已经有表反向生成实体,以3.3.*为例: php bin/console doctrine:mapping:import --force AppBundle xml 从现有 ...

  2. go学习笔记-语言基础

    语言基础 结构 基础组成: 包声明 引入包 函数 变量 语句 & 表达式 注释 程序 在开始编写应用之前,我们先从最基本的程序开始,在学习大部分语言之前,都会编写一个可以输出hello wor ...

  3. debounce、throttle、requestAnimationFrame

    今天review同事代码,代码实现了返回顶部的功能,用到了lodash库中的throttle,我看着眼生,于是乎去看了下lodash文档,然后牵出了debounce,具体的知识点,这里不再赘述,底部的 ...

  4. flask与javascript及ajax

    flask与javascript及ajax 1.      flask+js 1.1.    最简单的 最简单的元素信息改变. {% block content %} <h1>我的第一张网 ...

  5. java 上溯造型与下塑造型

    父类: package com.neusoft.chapter07; public class Father { public int i = 1; public void say(){ System ...

  6. RedHat6.4 安装yum源

    主要参考: http://blog.itpub.net/25313300/viewspace-708509/ http://blog.sina.com.cn/s/blog_50f908410101ct ...

  7. Centos7下lamp环境搭建的小笔记

    刚刚把校赛弄完,赛前在环境搭建上花了蛮多时间,也正好记一下笔记 0.首先更新源 清华大学开源镜像站的源 https://mirrors.tuna.tsinghua.edu.cn/help/centos ...

  8. Mysql综合练习作业50题

    #作业库create database db8 charset utf8; #年级表create table class_grade(gid int not null primary key auto ...

  9. 「暑期训练」「基础DP」 Monkey and Banana (HDU-1069)

    题意与分析 给定立方体(个数不限),求最多能堆叠(堆叠要求上方的方块严格小于下方方块)的高度. 表面上个数不限,问题是堆叠的要求决定了每个方块最多可以使用三次.然后就是对3n" role=& ...

  10. 怎样安装Python3

    在浏览器地址栏输入https://www.python.org/ 打开Python官网 好了,安装完成了! 可以把安装路径C:\Users\Administrator\AppData\Local\Pr ...