bzoj1444
Posted 123456
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1444相关的知识,希望对你有一定的参考价值。
1444: [Jsoi2009]有趣的游戏
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1191 Solved: 422
[Submit][Status][Discuss]
Description
Input
注意 是0<=P
Output
Sample Input
Sample Output
HINT
30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.
Source
要省选了 好慌啊 我什么都不会啊 只会抄答案啊
抄了个答案 并不是很懂...
为什么我的ac自动机不对,找了个模板才对...
为什么不可以直接高斯消元啊...
先建立ac自动机,然后我们有了张trie图,trie图是由trie树和fail指针组成的。
那么我们求的就是那些单词末尾的点走到的概率。trie图是一张有向有环图,那么我们不能直接dp...就得用高斯消元解方程。
但是为什么不可以直接解啊...等待填坑 一份抄来的代码
#include<bits/stdc++.h> using namespace std; const int N = 110; const double eps = 1e-8; int n, m, l, root, size, fail; int q[N], pos[N]; double p[N], a[N][N]; namespace ac { struct data { int danger, fail; int c[30]; } t[N]; void ins(char s[], int id) { int now = root; for(int i = 0; i < l; ++i) { if(!t[now].c[s[i] - ‘A‘]) t[now].c[s[i] - ‘A‘] = ++size; now = t[now].c[s[i] - ‘A‘]; } // printf("now=%d\n", now); t[now].danger = 1; pos[id] = now; } void get_fail() { int l = 1, r = 0; for(int i = 0; i < m; ++i) if(t[0].c[i]) q[++r] = t[0].c[i]; while(l <= r) { int u=q[l++]; t[u].danger |= t[t[u].fail].danger; for(int i=0; i<m; i++) { int &v = t[u].c[i]; if(!v) v = t[t[u].fail].c[i]; else t[v].fail = t[t[u].fail].c[i], q[++r]=v; } } } } using namespace ac; namespace gauss { void build() { a[0][size + 1] = -1.0; for(int i = 0; i <= size; ++i) { a[i][i] = -1.0; if(t[i].danger) continue; for(int j = 0; j < m; ++j) { // printf("i=%d child=%d\n", i, t[i].c[j]); a[t[i].c[j]][i] += p[j]; } } } void Gauss() { for(int now = 0; now <= size; ++now) { int x = now; for(int i = now; i <= size; ++i) if(abs(a[i][now]) > abs(a[x][now]) ) x = i; for(int i = 0; i <= size + 1; ++i) swap(a[x][i], a[now][i]); double t = a[now][now]; for(int i = now; i <= size + 1; ++i) a[now][i] /= t; for(int i = 0; i <= size; ++i) if(i != now) { double t = a[i][now]; for(int j = now; j <= size + 1; ++j) a[i][j] -= a[now][j] * t; } } } } int main() { using namespace gauss; scanf("%d%d%d", &n, &l, &m); for(int i = 0; i < m; ++i) { double a, b; scanf("%lf%lf", &a, &b); p[i] = a / b; if(fabs(p[i]) < eps) ++fail; } if(fail == m) { for(int i = 1; i <= n; ++i) puts("0.00"); return 0; } for(int i = 1; i <= n; ++i) { char s[N]; scanf("%s", s); ins(s, i); } get_fail(); build(); Gauss(); for(int i = 1; i <= n; ++i) { double t = a[pos[i]][size + 1]; if(fabs(t) < eps) puts("0.00"); else printf("%.2f\n", t); } return 0; }
以上是关于bzoj1444的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1444[Jsoi2009]有趣的游戏 AC自动机+概率DP+矩阵乘法