您的位置:首页 > 其它

BZOJ 2553: [BeiJing2011]禁忌【ACAM + 期望dp + 矩快优化

2016-12-04 10:52 393 查看
……反正瞎瘠薄搞搞,都是显然的

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define MAXN 80
using namespace std; int n,m,ji;

struct Matrix{
long double d[MAXN][MAXN];
int x,y;
Matrix():x(0),y(0){memset(d,0,sizeof d);}
Matrix(int w):x(w),y(w){
memset(d,0,sizeof d);
for(int i=0;i<w;++i) d[i][i] = 1;
}
Matrix(int x,int y):x(x),y(y){memset(d,0,sizeof d);}

Matrix operator * (const Matrix ano) {
Matrix RTN(x,ano.y);
for(register int i=0;i<x;++i)
for(register int j=0;j<y;++j)
for(register int k=0;k<ano.y;++k)
RTN.d[i][k] += d[i][j] * ano.d[j][k];
return RTN;
}

inline Matrix pow(int c){
Matrix TMP = *this , RTN(x);
for(;c;c>>=1,TMP=TMP*TMP)
if(c&1)
RTN = RTN * TMP;
return RTN;
}

void write(){
puts("");
for(register int i=0;i<x;++i)
for(register int j=0;j<y;++j)
printf("%.0Lf%c",d[i][j],j==y-1?'\n':' ');
puts("");
}
}INIT,TRANS;

long double f[MAXN][MAXN];
long double ans = 0;
long double p;
struct ACAM{
int son[MAXN][26];
int cnt_node,root;
int fail[MAXN];
int tag[MAXN];

inline void init(){
root = cnt_node = 1;
}

char s[20];
inline void insert(int now){
scanf("%s",s);
for(char *i = s;*i;++i){
int x = (*i) - 'a';
if ( !son[now][x] ) son[now][x] = ++cnt_node;
now = son[now][x];
}
tag[now] = 1;
}

int que[MAXN],head,tail;
inline void bfs(int now){
head = tail = 1;
que[0] = now;
for(register int x=0;x<ji;++x)
if(son[now][x]) fail[ son[now][x] ] = now , que[tail++] = son[now][x];
else son[now][x] = now;
while(head^tail){
now = que[head++];
for(register int x=0;x<ji;++x)
if(son[now][x])
fail[ son[now][x] ] = son[ fail[now] ][x] ,
que[tail++] = son[now][x] ,
tag[ son[now][x] ] |= tag[fail[son[now][x]]];
else son[now][x] = son[ fail[now] ][x];
}
}

inline void DP(int len){
++cnt_node;
INIT = Matrix(cnt_node,1);
INIT.d[1][0] = 1;
TRANS = Matrix(cnt_node,cnt_node);
for(register int i=1;i<cnt_node;++i)
for(register int x=0;x<ji;++x){
int aim = son[i][x];
if(!tag[aim]) TRANS.d[aim][i] += p;
else{
TRANS.d[1][i] += p;
TRANS.d[0][i] += p;
}
}
TRANS.d[0][0] = 1;

INIT = TRANS.pow(len) * INIT;
printf("%.6Lf",INIT.d[0][0]);
// f[0][1] = 1;
// for(int i=0;i<len;++i){
// for(int j=0;j<tail;++j){
// int now = que[j];
// for(int k = 0;k<ji;++k){
// if(tag[son[now][k]])
// ans += f[i][now]*p , f[i+1][root] += f[i][now]*p;
// else f[i+1][son[now][k]] += f[i][now]*p;
// }
// }
// }
// printf("%.6Lf",ans);
}
}YJQ;

int main(){
YJQ.init();
scanf("%d%d%d",&n,&m,&ji);
p = (double)1/ji;
for(register int i=1;i<=n;++i) YJQ.insert(YJQ.root);
YJQ.bfs(YJQ.root);
YJQ.DP(m);

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