BZOJ 2553: [BeiJing2011]禁忌(AC自动机+期望DP+矩阵快速幂)
2018-04-04 10:48
405 查看
传送吧
https://www.lydsy.com/JudgeOnline/problem.php?id=2553思路
建出trie图。记f[i][j]为长度为i到节点j的期望。直接转移不行。建出trie图的邻接矩阵,然后自乘len-1次转移。
具体就是如果当前点的儿子是禁忌点,就连向根(由儿子连长度多了1),否则连向儿子。这样就避免了重叠。而且有个显然的结论就是能走到禁忌点就走,肯定能取到最大值。
我们在每条边上放上概率,将值放在一个新建的点上,然后能走到禁忌点就连向它。不能放在根是显然的。转移就相当于i->k,k->j贡献i->j,就是在trie图上有方向的走(没方向考虑高消),然后统计答案。问的是从根走len步走到最终点的期望。
这道题告诉我们算期望可以先考虑概率,将值放在最后再乘。
long double是必要的,其他细节看代码。
代码
#include <bits/stdc++.h> #define maxn 105 using namespace std; int n, len, alp, cnt; char x[maxn]; struct AC{ AC *son[26], *fail; int ep, id; void Clear(){ for(int i = 0; i < 26; i++) son[i] = NULL; ep = 0; id = cnt; } }Node[maxn], *Root, *q[maxn]; struct Mat{ int r, c; long double A[maxn][maxn]; void Clear(){ memset(A, 0, sizeof(A)); } }f; AC *NewTnode(){ Node[cnt].Clear(); return Node+cnt++; } void Insert(char *s){ AC *now = Root; for(; *s != '\0'; s++){ int pos = (*s) - 'a'; if(!now->son[pos]) now->son[pos] = NewTnode(); now = now->son[pos]; } now->ep = 1; } void Build(){ int hh = 0, tt = 0; q[hh] = Root; Root->fail = NULL; while(hh <= tt){ AC *now = q[hh++]; for(int i = 0; i < alp; i++){ if(now->son[i]){ q[++tt] = now->son[i]; now->son[i]->fail = (now == Root) ? Root : now->fail->son[i]; now->son[i]->ep |= now->son[i]->fail->ep; } else now->son[i] = (now == Root) ? Root : now->fail->son[i]; } } } Mat operator * (Mat X, Mat Y){ Mat Z; Z.r = X.r; Z.c = Y.c; Z.Clear(); for(int i = 0; i <= X.r; i++) for(int j = 0; j <= Y.c; j++) for(int k = 0; k <= X.c; k++) Z.A[i][j] = (Z.A[i][j] + X.A[i][k] * Y.A[k][j]); return Z; } Mat Pow(Mat X){ Mat Z = X; len --; while(len){ if(len & 1) Z = Z * X; X = X * X; len >>= 1; } return Z; } int main(){ scanf("%d%d%d", &n, &len, &alp); Root = NewTnode(); for(int i = 1; i <= n; i++){ scanf("%s", x); Insert(x); } Build(); f.r = f.c = cnt; f.Clear(); f.A[cnt][cnt] = 1.0; long double possi = 1.0 / alp; for(int i = 0; i < cnt; i++){ AC *now = Node+i; for(int j = 0; j < alp; j++){ if(now->son[j]->ep){ f.A[i][0] += possi; f.A[i][cnt] += possi; continue; } f.A[i][now->son[j]->id] += possi; } } f = Pow(f); printf("%.7Lf\n", f.A[0][cnt]); return 0; }
What a good thing we lose
多么幸运 我们错失彼此
What a bad thing we knew
何其不幸 我们曾经相知
相关文章推荐
- [AC自动机 矩阵快速幂 期望] BZOJ 2553 [BeiJing2011]禁忌
- 【BZOJ 2553】[BeiJing2011]禁忌 AC自动机+期望概率dp
- 【BZOJ2553】【BeiJing2011】禁忌 AC自动机 矩阵乘法 动态规划
- 【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法
- BZOJ2553: [BeiJing2011]禁忌 AC自动机 期望DP 矩阵
- BZOJ 2553: [BeiJing2011]禁忌【ACAM + 期望dp + 矩快优化
- BZOJ - 2553 :禁忌(AC自动机+贪心+奇怪的矩阵)
- poj 2778 AC自动机+dp矩阵快速幂
- BZOJ 2553 BeiJing2011 禁忌 AC自动机+矩阵乘法
- BZOJ2553 Beijing2011禁忌(AC自动机+动态规划+矩阵快速幂+概率期望)
- 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂
- 【 bzoj 2553 】 [BeiJing2011]禁忌 - AC自动机+矩阵乘法
- [矩阵快速幂 DP] BZOJ 4037 [HAOI2015]数字串拆分 & BZOJ 2323 [ZJOI2011]细胞
- bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法
- 【bzoj2553】[BeiJing2011]禁忌
- bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法+期望
- BZOJ2553:[BeiJing2011]禁忌 AC自动机+矩阵快速幂
- [BZOJ2553] [BeiJing2011]禁忌-AC自动机-概率
- bzoj2510 弱题 【期望dp+循环矩阵快速幂】
- BZOJ2553 [BeiJing2011]禁忌 【AC自动机 + dp + 矩乘优化】