BZOJ 1444 [JSOI2009]有趣的游戏 (Trie图/AC自动机+矩阵求逆)
题目大意:给你$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自动机+矩阵求逆)的更多相关文章
- BZOJ 1444:[JSOI2009]有趣的游戏
BZOJ 1444:[JSOI2009]有趣的游戏 题目链接 首先我们建出Trie图,然后高斯消元. 我们设\(f_i\)表示经过第\(i\)个点的期望次数: \[ f_x=\sum i\cdot p ...
- BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]
1444: [Jsoi2009]有趣的游戏 题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率 套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩 ...
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
1444: [Jsoi2009]有趣的游戏 4820: [Sdoi2017]硬币游戏 这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题. 第一题数据范围较小,将串建成AC自动机以后,以A ...
- BZOJ 1444 [Jsoi2009]有趣的游戏 (AC自动机 + 概率DP + Gauss)
1444: [Jsoi2009]有趣的游戏 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1382 Solved: 498[Submit][Statu ...
- ●BZOJ 1444 [Jsoi2009]有趣的游戏
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1444题解.1: 概率dp,矩阵乘法,快速幂. 对所有串建立AC自动机, 那么如果在trie树 ...
- bzoj 1444: [Jsoi2009]有趣的游戏【AC自动机+dp+高斯消元】
https://blog.sengxian.com/solutions/bzoj-1444 orz 一直是我想错了,建出AC自动机之后,实际上这个定义是设f[i]为经过i节点的 * 期望次数 * ,因 ...
- BZOJ 1444 [JSOI2009]有趣的游戏 (AC自动机、概率与期望DP、矩阵乘法)
诶这题洛谷居然没有??? 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1444 题解: 我见到主要有三种做法. 一是矩阵乘法.设\(d ...
- BZOJ 1444: [Jsoi2009]有趣的游戏 AC自动机+概率与期望+矩阵乘法
这道题还比较友好~首先,构建出来 $AC$ 自动机,那么我们要求的就是从 $0$ 号点走无限次走到一个终止节点的概率. 考虑构建转移矩阵 $M,$ $M_{i,j}$ 表示节点 $i$ 转移到节点 $ ...
- 1444: [Jsoi2009]有趣的游戏
1444: [Jsoi2009]有趣的游戏 链接 分析: 如果一个点回到0号点,那么会使0号点的概率增加,而0号点的概率本来是1,不能增加,所以这题用期望做. 设$x_i$表示经过i的期望次数,然后初 ...
随机推荐
- Springboot统一异常处理(@ControllerAdvice)
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind ...
- Oracle的分页查询及内联视图和函数处理
1.Oracle的分页常用方式: select * from(select * ,ROWNUM num from table where ROWNUM<=20 ) where num>0; ...
- 记录——本地minikube安装ubuntu镜像总是报 Back-off restarting failed container问题 -已解决(更新)
1.环境介绍 使用本机系统:macX minikube镜像:安装的阿里云提供的镜像(否则总是提示访问google的api,不FQ无法成功) 虚拟机情况:使用Virtual box 的虚拟机环境 min ...
- jq——DOM文档处理
内部插入:父子级关系 1 $(a).append($(b))把b插入到a里面(a里面的面后) $("div").append($("<p>段落</p&g ...
- 树莓派(Raspberry Pi):完美的家用服务器
出处:http://linux.cn/thread/11884/1/1/ 树莓派(Raspberry Pi):完美的家用服务器 自从树莓派发布后,所有在互联网上的网站为此激动人心的设备提供了很多有趣和 ...
- [51nod1074]约瑟夫环V2
N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到K的人出列,后面的人重新从1开始报数.问最后剩下的人的编号. 例如:N = 3,K = 2.2号先出列,然后是1号,最后剩下的是3号. ...
- Python学习笔记(5)practice:shopping_cart
2019-02-27 原代码: money = int(input("请输入金额:")) list = ["phone", "clothes" ...
- 我一不小心把ubuntu里的ps这样的命令删掉了,应该怎么重装呢
sudo apt-get --reinstall install procps
- COGS——T 1175. [顾研NOIP] 旅游电车
http://www.cogs.pro/cogs/problem/problem.php?pid=1175 ★★☆ 输入文件:buss.in 输出文件:buss.out 简单对比时间限制: ...
- Android ToolBar 的简单封装
使用过 ToolBar 的朋友肯定对其使用方法不陌生,由于其使用方法非常easy.假设对 ActionBar 使用比較熟练的人来说.ToolBar 就更easy了!只是,相信大家在使用的过程中都遇到过 ...