题目链接

BZOJ2553

题解

话说在前,此题卡精度,最好开long double

先建\(AC\)自动机

求期望,逆着求,设\(f[i][j]\)为长度为\(i\)的串,当前匹配AC自动机\(j\)节点,之后能产生伤害的期望值

枚举转移,如果转移到一个单词节点,因为产生伤害的单词间不能相连,就直接跳回根节点

矩乘优化一下即可

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#include<iomanip>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 80,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
char s[6][20];
int n,L,A,len[6];
int ch[maxn][26],fail[maxn],val[maxn],cnt;
void ins(int p){
int u = 0,id;
for (int i = 1; i <= len[p]; i++){
id = s[p][i] - 'a';
u = ch[u][id] ? ch[u][id] : (ch[u][id] = ++cnt);
}
val[u] = true;
}
void dfs(int u,int f){
if (val[f]) val[u] = true;
for (int i = 0; i < A; i++)
if (ch[u][i]) dfs(ch[u][i],u);
}
void getf(){
queue<int> q;
for (int i = 0; i < A; i++) if (ch[0][i]) q.push(ch[0][i]);
int u,v;
while (!q.empty()){
u = q.front(); q.pop();
for (int i = 0; i < A; i++){
v = ch[u][i];
if (!v){
ch[u][i] = ch[fail[u]][i];
continue;
}
fail[v] = ch[fail[u]][i];
q.push(v);
}
}
}
struct Matrix{
long double s[maxn][maxn];
int n,m;
Matrix(){cls(s);n = m = 0;}
}C,F;
inline Matrix operator *(const Matrix& a,const Matrix b){
Matrix c;
if (a.m != b.n) return c;
c.n = a.n; c.m = b.m;
for (int i = 0; i < c.n; i++)
for (int j = 0; j < c.m; j++)
for (int k = 0; k < a.m; k++)
c.s[i][j] += a.s[i][k] * b.s[k][j];
return c;
}
inline Matrix qpow(Matrix a,int b){
Matrix re; re.n = re.m = a.n;
for (int i = 0; i < re.n; i++) re.s[i][i] = 1;
for (; b; b >>= 1,a = a * a)
if (b & 1) re = re * a;
return re;
}
int main(){
n = read(); L = read(); A = read();
REP(i,n){
scanf("%s",s[i] + 1),len[i] = strlen(s[i] + 1);
ins(i);
}
dfs(0,0);
getf();
C.n = C.m = cnt + 2; long double x = 1.0 / A;
for (int i = 0; i <= cnt; i++){
if (val[i]) continue;
for (int j = 0; j < A; j++){
if (val[ch[i][j]]){
C.s[i][cnt + 1] += x;
C.s[i][0] += x;
}
else {
C.s[i][ch[i][j]] += x;
}
}
}
C.s[cnt + 1][cnt + 1] = 1;
F.n = cnt + 2; F.m = 1;
F.s[cnt + 1][0] = 1;
Matrix Fn = qpow(C,L) * F;
long double ans = Fn.s[0][0];
cout << fixed <<setprecision(12) << ans<<endl;
return 0;
}

BZOJ2553 [BeiJing2011]禁忌 【AC自动机 + dp + 矩乘优化】的更多相关文章

  1. BZOJ2553[BeiJing2011]禁忌——AC自动机+概率DP+矩阵乘法

    题目描述 Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi恢复了读心的能力…… 如今,在John已经成为传 ...

  2. BZOJ2553 [BeiJing2011]禁忌 AC自动机 矩阵

    原文链接http://www.cnblogs.com/zhouzhendong/p/8196279.html 题目传送门 - BZOJ2553 题意概括 引用一下lych大佬的: 在字母只有前alph ...

  3. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  4. 【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法

    [BZOJ2553][BeiJing2011]禁忌 Description Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平. ...

  5. bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2553 题解: 利用AC自动机的dp求出所有的转移 然后将所有的转移储存到矩阵中,进行矩阵 ...

  6. bzoj 2553 [BeiJing2011]禁忌——AC自动机+概率DP+矩阵

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2553 看了题解才会…… 首先,给定一个串,最好的划分方式是按禁忌串出现的右端点排序,遇到能填 ...

  7. 【BZOJ 2553】[BeiJing2011]禁忌 AC自动机+期望概率dp

    我一开始想的是倒着来,发现太屎,后来想到了一种神奇的方法——我们带着一个既有期望又有概率的矩阵,偶数(2*id)代表期望,奇数(2*id+1)代表概率,初始答案矩阵一列,1的位置为1(起点为0),工具 ...

  8. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  9. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

随机推荐

  1. 一些窍门 drawable

    java.lang.Object       android.graphics.drawable.DrawableKnown Direct Subclasses   BitmapDrawable, C ...

  2. Qt 独立运行时伴随CMD命令窗口

    用Qt写了一个小软件,在把程序release后,打包分装后,发现程序运行的时候会伴随cmd命令窗口,可把我愁怀了 不过功夫不负有心人,在老师和我网友的帮助下,终于搞完了 CONFIG:指定工程配置和编 ...

  3. Navicat和DBeaver的查询快捷键

    1.Navicat for MySQL(连接MySQL数据库的工具) ctrl + r 执行查询页中所有的sql语句 ctrl + shift + r 只运行选中的sql语句 2.DBeaver(支持 ...

  4. Java反射篇学习笔记

    今天重新学习了java中的反射,写一篇学习笔记总结一下.代码基本都是照着两篇博客敲的: 参考一:   https://blog.csdn.net/sinat_38259539/article/deta ...

  5. Python3 下安装python-votesmart

    在python2下安装python-smart还比较容易,而python3中由于很多函数库的变化直接使用python setup.py install 命令来安装的话会导致错误,而导致错误的原因就是p ...

  6. NMAP-高级用法

    1.报文分段 2.偏移 –mtu后面的数字是8的倍数 3.源端口欺骗 4.指定报文长度 5.ttl 6.mac地址伪造 0代表随机伪造 7.正常输出 8.输出为xml 9.输出为grep 10.输出所 ...

  7. php中array_map和array_walk的使用对比

    一.array_map() 1.array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组,若函数作用后无返回值,则对应的新值数组中为空. 2.回调 ...

  8. LintCode-380.两个链表的交叉

    两个链表的交叉 请写一个程序,找到两个单链表最开始的交叉节点. 注意事项 如果两个链表没有交叉,返回null. 在返回结果后,两个链表仍须保持原有的结构. 可假定整个链表结构中没有循环. 样例 下列两 ...

  9. centOS6.5如何从启动界面直接进入命令行界面

    进入系统后,按Ctrl+Alt+Fn可以切换控制台,其中F1~F6是字符控制台,F7~F12是X控制台 如果启动直接进入字符控制台,而不是X Window,可以编辑/etc/inittab将id:5: ...

  10. 【Linux】- mv命令

    Linux mv命令用来为文件或目录改名.或将文件或目录移入其它位置. 语法 mv [options] source dest mv [options] source... directory 参数说 ...