【BZOJ 2553】[BeiJing2011]禁忌 AC自动机+期望概率dp
我一开始想的是倒着来,发现太屎,后来想到了一种神奇的方法——我们带着一个既有期望又有概率的矩阵,偶数(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的更多相关文章
- 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂
[题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...
- bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2553 题解: 利用AC自动机的dp求出所有的转移 然后将所有的转移储存到矩阵中,进行矩阵 ...
- bzoj 2553 [BeiJing2011]禁忌——AC自动机+概率DP+矩阵
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2553 看了题解才会…… 首先,给定一个串,最好的划分方式是按禁忌串出现的右端点排序,遇到能填 ...
- 【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法
[BZOJ2553][BeiJing2011]禁忌 Description Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平. ...
- 【BZOJ 3811】玛里苟斯 大力观察+期望概率dp+线性基
大力观察:I.从输出精准位数的约束来观察,一定会有猫腻,然后仔细想一想,就会发现输出的时候小数点后面不是.5就是没有 II.从最后答案小于2^63可以看出当k大于等于3的时候就可以直接搜索了 期望概率 ...
- BZOJ2553[BeiJing2011]禁忌——AC自动机+概率DP+矩阵乘法
题目描述 Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi恢复了读心的能力…… 如今,在John已经成为传 ...
- BZOJ2553 [BeiJing2011]禁忌 AC自动机 矩阵
原文链接http://www.cnblogs.com/zhouzhendong/p/8196279.html 题目传送门 - BZOJ2553 题意概括 引用一下lych大佬的: 在字母只有前alph ...
- BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )
建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...
- BZOJ 3270 博物馆 && CodeForces 113D. Museum 期望概率dp 高斯消元
大前提,把两个点的组合看成一种状态 x 两种思路 O(n^7) f[x]表示在某一个点的前提下,这个状态经过那个点的概率,用相邻的点转移状态,高斯一波就好了 O(n^6) 想象成臭气弹,这个和那个的区 ...
随机推荐
- 强化记忆之php
php 输出的区分 新手摸索道路,有说不对的地方,还请多多包涵. echo 能够输出一个以上的字符串,也能输出html标签 print 一次只能接受一个字符串(区分与echo),也能输出html标签 ...
- 响应式布局--设置rem自适应
//designWidth:设计稿的实际宽度值,需要根据实际设置 //maxWidth:制作稿的最大宽度值,需要根据实际设置 //这段js的最后面有两个参数记得要设置,一个为设计稿实际宽度,一个为制作 ...
- 《linux设备驱动开发详解》笔记——15 linux i2c驱动
结合实际代码和书中描述,可能跟书上有一定出入.本文后续芯片相关代码参考ZYNQ. 15.1 总体结构 如下图,i2c驱动分为如下几个重要模块 核心层core,完成i2c总线.设备.驱动模型,对用户提供 ...
- 修复网站漏洞对phpmyadmin防止被入侵提权的解决办法
phpmyadmin是很多网站用来管理数据库的一个系统,尤其是mysql数据库管理的较多一些,最近phpmysql爆出漏洞,尤其是弱口令,sql注入漏洞,都会导致mysql的数据账号密码被泄露,那么如 ...
- 完全数--Python
如果一个数恰好等于它的因子之和,则称该数为“完全数” [1] .各个小于它的约数(真约数,列出某数的约数,去掉该数本身,剩下的就是它的真约数)的和等于它本身的自然数叫做完全数(Perfect num ...
- Zookeeper系列(二) Zookeeper配置说明
在配置ZooKeeper配置文件时,有些参数是必需的,有些参数是可选的,这些必需的参数构成了Zookeeper配置文件的最低配置要求,如果需要对ZooKeeper进行更详细的配置,可以 ...
- 【转】Django添加静态文件设置
STATIC_URL = '/statics/'STATIC_ROOT= os.path.join(BASE_DIR, 'statics')STATICFILES_DIRS = ( os.path.j ...
- express操作数据库
Express 首页 入门 使用指南 API 中文手册 进阶话题 有用的资源 集成数据库 为 Express 应用添加连接数据库的能力,只需要加载相应数据库的 Node.js 驱动即可.这里将会简要介 ...
- 怎样安装Python3
在浏览器地址栏输入https://www.python.org/ 打开Python官网 好了,安装完成了! 可以把安装路径C:\Users\Administrator\AppData\Local\Pr ...
- LINQ学习笔记——(1)添加扩展方法
目的: 对已存在类型的行为进行扩展 注意事项: 扩展方法是一种特殊的静态方法 扩展方法必须在静态类中定义 扩展方法的优先级低于同名的类方法 扩展方法只在特定的命名空间内有效 ...