您的位置:首页 > Web前端 > JavaScript

Bzoj1444 [Jsoi2009]有趣的游戏

2017-01-23 22:15 423 查看

 

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1075  Solved: 367

Description

Input

注意 是0<=P

Output

Sample Input


Sample Output


HINT

 

 30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.

 

Source

 

概率

AC自动机+矩阵乘法

 

先建好AC自动机,得到不同字母间的转移关系。

对于每个结点,如果它是某个玩家的字符串末,则它转移到自己的概率为1,否则按照读入的概率转移到不同的字母去。

↑以此构建转移矩阵。

精度要求1-e2,那么尝试矩阵暴力自乘,使得概率趋于稳定。自乘30次精度不够,会WA,40次就过了。

 

/*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int mxn=50;
int n,l,m;
struct Aca{
int t[300][12];
int fail[300],end[300];
int pos[300];
int cnt,rt,id;
void clear(){
cnt=0;memset(t,0,sizeof t);memset(fail,0,sizeof fail);
rt=++cnt;id=0;
return;
}
void insert(char s[]){
int len=strlen(s);
int now=rt;
for(int i=0;i<len;i++){
if(!t[now][s[i]-'A'])
t[now][s[i]-'A']=++cnt;
now=t[now][s[i]-'A'];
}
end[now]++;
pos[++id]=now;//记录每个串末尾的结点编号
return;
}
void Build(){
queue<int>q;
int i,j;
for(i=0;i<m;i++){
if(t[rt][i]){
q.push(t[rt][i]);
fail[t[rt][i]]=rt;
}
else t[rt][i]=rt;
}
while(!q.empty()){
int u=q.front();q.pop();
for(i=0;i<m;i++){
if(t[u][i]){
q.push(t[u][i]);
fail[t[u][i]]=t[fail[u]][i];
}
else t[u][i]=t[fail[u]][i];
}
}
}
};
Aca a;//AC自动机
//
struct Matrix{
double c[130][130];
int x;
void clear(){memset(c,0,sizeof c);x=0;return;}
friend Matrix operator * (Matrix a,Matrix b){
Matrix res;
res.clear();
res.x=a.x;
for(int i=1;i<=a.x;i++){
for(int j=1;j<=a.x;j++){
for(int k=1;k<=a.x;k++){
res.c[i][j]+=a.c[i][k]*b.c[k][j];
}
}
}
return res;
}
}mp;//矩阵乘
char s[mxn];
double p[mxn];
int main(){
int i,j,P,Q;
scanf("%d%d%d",&n,&l,&m);
for(i=1;i<=m;i++){
scanf("%d%d",&P,&Q);
p[i]=(double)P/Q;
}
a.clear();
for(i=1;i<=n;i++){
scanf("%s",s);
a.insert(s);
}
a.Build();
for(i=1;i<=a.cnt;i++){//统计概率
if(a.end[i]) mp.c[i][i]=1;
else for(j=0;j<m;j++){
mp.c[i][a.t[i][j]]+=p[j+1];
}
}
/*
for(i=1;i<=a.cnt;i++){
for(j=1;j<=a.cnt;j++){
printf("%.3f ",mp.c[i][j]);
}
printf("\n");
}
*/
mp.x=a.cnt;
for(i=1;i<=40;i++)
mp=mp*mp;
for(i=1;i<=n;i++)
printf("%.2f\n",mp.c[1][a.pos[i]]);
return 0;
}
/*
3 2 2
1 2
1 2
AB
BA
AA
*/

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: