题目大意:给你$N$个长度相等且互不相同的模式串,现在有一个字符串生成器会不断生成字符,其中每个字符出现的概率是$p_{i}/q_{i}$,当生成器生成的字符串包含了某个模式串,则拥有该模式串的玩家胜利,然后游戏立即结束,求每个玩家获胜的概率 $N<=10$

首先建出$Trie$图

接着设$f[i]$表示匹配时停在i的概率,可得$f[ch{k}]+=f[i]*p_{k}/q_{k}$

由于$N$很小,可以构建$dp$转移的邻接矩阵,由于生成器生成的串是无限长的,相当于把矩阵乘了无限次幂

可以耍赖一点...把矩阵自乘很多次,反正是保留小数卡精度过

正确的做法呢,就是利用等比数列求极限的方法,即$1/(1-p)$,1在这里是单位矩阵,$p$是邻接矩阵

然后对$(1-p)$这个矩阵求逆即可

 #include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define NN 105
#define maxn 100000
#define ll long long
#define dd double
#define uint unsigned int
#define mod 1000000007
#define idx(X) (X-'A')
#define eps (1e-9)
using namespace std; int n,m;
int ed[NN];
int p[],q[],L,num; struct M{
dd f[NN][NN*];
friend M operator * (const M &a,const M &b){
M ret;memset(&ret,,sizeof(ret));
for(int i=;i<n;i++)
for(int j=;j<n;j++)
for(int k=;k<n;k++)
ret.f[i][j]+=a.f[i][k]*b.f[k][j];
return ret;
}
int Gauss()
{
int nn=n*;
for(int i=;i<n;i++)
f[i][i+n]=;
for(int i=;i<n;i++)
{
for(int j=i;j<n;j++)
if(fabs(f[j][i])>eps){
for(int k=;k<nn;k++)
swap(f[i][k],f[j][k]);
break;
}
if(fabs(f[i][i])<eps) return ;
dd r=1.0/f[i][i];
for(int j=i;j<nn;j++)
f[i][j]*=r;
for(int j=;j<n;j++)
if(j!=i){
r=f[j][i];
for(int k=i;k<nn;k++)
f[j][k]=f[j][k]-r*f[i][k];
}
}
for(int i=;i<n;i++)
for(int j=;j<n;j++)
f[i][j]=f[i][j+n];
return ;
}
}; struct AC{
int ch[NN][],fail[NN],tot,win[NN];
void Build_Trie(char *str,int len,int id)
{
int x=;
for(int i=;i<=len;i++){
if(!ch[x][idx(str[i])])
ch[x][idx(str[i])]=++tot;
x=ch[x][idx(str[i])];
}ed[id]=x;win[x]=;
}
void Build_Fail()
{
queue<int>q;
for(int i=;i<m;i++)
if(ch[][i]) q.push(ch[][i]);
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=;i<m;i++)
{
if(ch[x][i]){
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}else{
ch[x][i]=ch[fail[x]][i];
}
}
}
}
void Build_Martix(M &S)
{
for(int x=;x<=tot;x++)
if(!win[x]){
for(int i=;i<m;i++)
S.f[ch[x][i]][x]+=1.0*p[i]/q[i];
}
for(int i=;i<n;i++)
for(int j=;j<n;j++)
if(i!=j) S.f[i][j]=-S.f[i][j];
else S.f[i][j]=1.0-S.f[i][j];
}
}ac;
M ans,ni; int main()
{
//freopen("t1.in","r",stdin);
scanf("%d%d%d",&num,&L,&m);
for(int i=;i<m;i++)
scanf("%d%d",&p[i],&q[i]);
char str[];
for(int i=;i<=num;i++){
scanf("%s",str+);
ac.Build_Trie(str,L,i);}
ac.Build_Fail();
n=ac.tot+;
ac.Build_Martix(ans);
ans.Gauss();
for(int i=;i<=num;i++)
printf("%.2lf\n",ans.f[ed[i]][]);
return ;
}

BZOJ 1444 [JSOI2009]有趣的游戏 (Trie图/AC自动机+矩阵求逆)的更多相关文章

  1. BZOJ 1444:[JSOI2009]有趣的游戏

    BZOJ 1444:[JSOI2009]有趣的游戏 题目链接 首先我们建出Trie图,然后高斯消元. 我们设\(f_i\)表示经过第\(i\)个点的期望次数: \[ f_x=\sum i\cdot p ...

  2. BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]

    1444: [Jsoi2009]有趣的游戏 题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率 套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩 ...

  3. BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)

    1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...

  4. BZOJ 1444 [Jsoi2009]有趣的游戏 (AC自动机 + 概率DP + Gauss)

    1444: [Jsoi2009]有趣的游戏 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1382  Solved: 498[Submit][Statu ...

  5. ●BZOJ 1444 [Jsoi2009]有趣的游戏

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1444题解.1: 概率dp,矩阵乘法,快速幂. 对所有串建立AC自动机, 那么如果在trie树 ...

  6. bzoj 1444: [Jsoi2009]有趣的游戏【AC自动机+dp+高斯消元】

    https://blog.sengxian.com/solutions/bzoj-1444 orz 一直是我想错了,建出AC自动机之后,实际上这个定义是设f[i]为经过i节点的 * 期望次数 * ,因 ...

  7. BZOJ 1444 [JSOI2009]有趣的游戏 (AC自动机、概率与期望DP、矩阵乘法)

    诶这题洛谷居然没有??? 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1444 题解: 我见到主要有三种做法. 一是矩阵乘法.设\(d ...

  8. BZOJ 1444: [Jsoi2009]有趣的游戏 AC自动机+概率与期望+矩阵乘法

    这道题还比较友好~首先,构建出来 $AC$ 自动机,那么我们要求的就是从 $0$ 号点走无限次走到一个终止节点的概率. 考虑构建转移矩阵 $M,$ $M_{i,j}$ 表示节点 $i$ 转移到节点 $ ...

  9. 1444: [Jsoi2009]有趣的游戏

    1444: [Jsoi2009]有趣的游戏 链接 分析: 如果一个点回到0号点,那么会使0号点的概率增加,而0号点的概率本来是1,不能增加,所以这题用期望做. 设$x_i$表示经过i的期望次数,然后初 ...

随机推荐

  1. Unity 三维软件单位导入资源单位比例

    三维软件 内部米制尺寸/m 默认设置导入unity中的尺寸/m 与unity单位比例 Maya 1 100 1:100 3DS MAX 1 0.01 100:1 Cinema 4D 1 100 1:1 ...

  2. Pyhton学习——Day40

    #一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:# 核心(ECMAScript)# 文档对象模型(DOM) Document object model (整合js,css,ht ...

  3. C# Windows Api的一些方法 封装 以及 常用参数

    using System;using System.Collections.Generic;using System.Drawing;using System.Diagnostics;using Sy ...

  4. Node.js 指南(迁移到安全的Buffer构造函数)

    迁移到安全的Buffer构造函数 移植到Buffer.from()/Buffer.alloc() API. 概述 本指南介绍了如何迁移到安全的Buffer构造函数方法,迁移修复了以下弃用警告: 由于安 ...

  5. Python socket通信之FTP

    Python中利用socket进行server端和client端通信是网络编程的基础,是最简单的传输范例. (懂网络的请自动跳过这一部分) 首先,要想通信,必须建立连接,建立连接的过程,需要clien ...

  6. 2019-03-18 Python time 将2015年11月20日转换为2015-11-20

    #ReportingDate = soup.select('body > div.main > div > div.ctr > div.recruit > ul > ...

  7. js实现新闻滚动实例

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  8. 表单标签 fieldset legent

    书写表单时可以提供简单样式的标签 <fieldset> <legent></legent> <input type="text" > ...

  9. 【BZOJ 1305】[CQOI2009]dance跳舞

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 男生和女生每个人都分身成两个节点 即x[1],x[2]和y[1],y[2] 然后如果i和j不相互喜欢 那么add(x[i][2],y ...

  10. mysql5.7官网直译SQL语句优化--select语句优化

    8.2 sql语句优化 大致内容如下: 8.2.1:SELECT语句的优化 8.2.2:优化子查询,派生表和试图引用 8.2.3:优化INFORMATION_SCHEMA查询 8.2.4:优化数据改变 ...