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

【 bzoj 1444 】 [Jsoi2009]有趣的游戏 - AC自动机+矩阵乘法

2016-02-16 18:11 731 查看
  假设现在建好了一个AC自动机,那么接受一个串相当于从根节点走到单词节点。对应到这道题上,每走一步是有权值的(概率),就相当于无向图一样。这样只要把邻接矩阵建出来然后自乘一定次数就可以了。

  因为精度要求不太高,所以自乘个63次就完全够了233333

#include <bits/stdc++.h>
#define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++)
#define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --)

inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}

const int maxn = 207;

typedef int arr[maxn];

int n , m , tot , l;

arr val , pos , p , q , fail;

double prob[maxn];

char str[maxn][maxn];

int go[maxn][11];

inline void ins(char *s , int id) {
int u = 1;
for (char *_ = s + 1 ; *_ ; _ ++) {
int c = *_ - 'A' + 1;
if (!go[u][c]) go[u][c] = ++ tot;
u = go[u][c];
}
val[u] = id , pos[id] = u;
}

std::queue<int> Q;

inline void build() {
rep (c , 1 , m) {
int u = go[1][c];
if (u) Q.push(u) , fail[u] = 1;
else go[1][c] = 1;
}
while (!Q.empty()) {
int r = Q.front() ; Q.pop();
rep (c , 1 , m) {
int u = go[r][c];
if (!u) { go[r][c] = go[fail[r]][c] ; continue ; }
Q.push(u);
int v = fail[r];
//          while (v && !go[v][c]) v = fail[v];
fail[u] = go[v][c];
}
}
}

void input() {
n = rd() , l = rd() , m = rd() , tot = 1;
rep (i , 1 , m) p[i] = rd() , q[i] = rd() , prob[i] = (double) p[i] / q[i];
rep (i , 1 , n) scanf("%s" , str[i] + 1) , ins(str[i] , i);
}

struct matrix {
double a[maxn][maxn];
matrix() { memset(a , 0 , sizeof a); }
inline double* operator[](int x) {
return a[x];
}
inline void clear() {
rep (i , 1 , tot) rep (j , 1 , tot) a[i][j] = 0;
}
inline void operator=(matrix &t) {
rep (i , 1 , tot) rep (j , 1 , tot) a[i][j] = t[i][j];
}
inline void print() {
rep (i , 1 , tot) rep (j , 1 , tot) printf("%.2lf%c" , a[i][j] , j == tot ? '\n' : ' ');
puts("==========");
}
}A , B;

inline void mul() {
B = A;
//  A.print();
A.clear();
rep (i , 1 , tot) rep (j , 1 , tot) rep (k , 1 , tot)
A[i][j] += B[i][k] * B[k][j];
}

void solve() {
build();
rep (i , 1 , tot) if (val[i])
A[i][i] = 1.0;
else
rep (c , 1 , m)
A[i][go[i][c]] += prob[c];
rep (t , 0 , 63)
mul();
rep (i , 1 , n) printf("%.2lf\n" , A[1][pos[i]]);
}

int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: