【 bzoj 1444 】 [Jsoi2009]有趣的游戏 - AC自动机+矩阵乘法
2016-02-16 18:11
731 查看
假设现在建好了一个AC自动机,那么接受一个串相当于从根节点走到单词节点。对应到这道题上,每走一步是有权值的(概率),就相当于无向图一样。这样只要把邻接矩阵建出来然后自乘一定次数就可以了。
因为精度要求不太高,所以自乘个63次就完全够了233333
因为精度要求不太高,所以自乘个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; }
相关文章推荐
- javascript dom编程艺术阅读笔记
- js 代码的优化 ,完全是照搬,不过挺好使
- JavaScript权威指南__第三章
- 41条超级实用的JS 技巧
- JS如何创建对象和继承对象
- JavaScript字符串截取
- JS中关于clientWidth offsetWidth scrollWidth 等的含义
- 全面理解Javascript闭包和闭包的几种写法及用途
- javascript构造函数小记
- js知识点图解
- js 根据权重概率随机
- python 转换 Javascript %u 字符串为 python unicode
- js工具
- Javascript中的Prototype到底是什么
- JSP 千位分隔符
- 时间js
- Js作用域与作用域链详解
- JavaScript中的拖拽(以及Html5中的拖放)
- 30行代码实现Javascript中的MVC
- window.location属性详解