题解 洛谷 P4569 【[BJWC2011]禁忌】
考虑用\(AC\)自动机来解决本题这样的多字符串匹配问题。
要最大化魔法分割后得到的禁忌串数目,最优情况肯定为在一个串中每个禁忌串的右端点进行分割。对应到\(AC\)自动机上,就是匹配到一个禁忌串后,就直接转移到根节点。
若用朴素的\(DP\)解决,发现题目中的\(len\)过大,于是用矩阵快速幂优化。
先构造初始矩阵,\(a_{i,j}\)的值表示当串长为\(1\)时从状态\(i\)转移到状态\(j\)的概率,对这样的一个矩阵进行\(len\)次幂后,所得的含义即为串长为\(len\)时所对应的概率。
同时新增一个状态\(t\)来统计期望,若转移过程中,转移到了一个合法的状态,即匹配上了一个禁忌串,那么就可以把当前概率统计到状态\(t\)上了,最后直接查询根到状态\(t\)即可。
构造矩阵时,分情况讨论。设\(P=\frac{1}{alphabet}\),若一个状态\(x\)可转移到状态\(y\),若状态\(y\)不是禁忌串的终止状态,则\(a_{x,y}\)加上\(P\),否则让\(a_{x,root}\)加上\(P\)和\(a_{x,t}\)加上\(P\)。
具体实现细节看代码吧。
\(code:\)
#include<bits/stdc++.h>
#define maxn 110
using namespace std;
typedef long double ld;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,l,alph,tot,root;
ld P;
int trie[maxn][30],fail[maxn];
bool end[maxn];
char s[maxn];
struct matrix
{
ld a[maxn][maxn];
}m,e;
matrix operator *(const matrix &x,const matrix &y)
{
matrix z;
memset(z.a,0,sizeof(z.a));
for(int k=root;k<=tot+1;++k)
for(int i=root;i<=tot+1;++i)
for(int j=root;j<=tot+1;++j)
z.a[i][j]+=x.a[i][k]*y.a[k][j];
return z;
}
matrix qp(matrix x,int y)
{
matrix t=e;
while(y)
{
if(y&1) t=t*x;
x=x*x;
y>>=1;
}
return t;
}
void insert()
{
int len=strlen(s+1),p=root;
for(int i=1;i<=len;++i)
{
int ch=s[i]-'a';
if(!trie[p][ch]) trie[p][ch]=++tot;
p=trie[p][ch];
}
end[p]=true;
}
void build()
{
queue<int> q;
for(int i=0;i<alph;++i)
if(trie[root][i])
q.push(trie[root][i]);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<alph;++i)
{
int y=trie[x][i];
if(y)
{
fail[y]=trie[fail[x]][i];
end[y]|=end[fail[y]],q.push(y);
}
else trie[x][i]=trie[fail[x]][i];
}
}
e.a[tot+1][tot+1]=m.a[tot+1][tot+1]=1;
for(int x=root;x<=tot;++x)
{
e.a[x][x]=1;
for(int ch=0;ch<alph;++ch)
{
int y=trie[x][ch];
if(end[y]) m.a[x][tot+1]+=P,m.a[x][root]+=P;
else m.a[x][y]+=P;
}
}
}
int main()
{
read(n),read(l),read(alph),P=(ld)1.0/(ld)alph;
for(int i=1;i<=n;++i)
scanf("%s",s+1),insert();
build(),m=qp(m,l);
printf("%Lf",m.a[root][tot+1]);
return 0;
}
题解 洛谷 P4569 【[BJWC2011]禁忌】的更多相关文章
- 洛谷 P4569 - [BJWC2011]禁忌(AC 自动机+矩阵乘法)
题面传送门 又好久没做过 AC 自动机的题了,做道练练手罢( 首先考虑对于某个固定的字符串怎样求出它的伤害,我们考虑贪心,每碰到出现一个模式串就将其划分为一段,最终该字符串的代价就是划分的次数.具体来 ...
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- 题解-洛谷P5217 贫穷
洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...
- 题解 洛谷 P2010 【回文日期】
By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...
随机推荐
- Python数据可视化实战:实时更新海外疫情数据,实现数据可视化
前言 我国的疫情已经得到了科学的控制,开始了全面的复工复产,但是国外的疫情却“停不下来”.国外现在可谓就是处于水深火热当中啊,病毒极强的传染性,导致了许多的人都“中招”了,我国已经全面复工复产了,人大 ...
- elk4
传统问题: 微服务系统下服务器数量过大,如果还在使用依次登录每台机器的传统方法查询日志,这样效率非常低下.ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写 ...
- junit配合catubuter统计单元测试的代码覆盖率
1.视频参考孔浩老师ant视频笔记 对应的build-junit.xml脚步如下所示: <?xml version="1.0" encoding="UTF-8&qu ...
- 深入理解JVM(③)虚拟机的类加载时机
前言 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称为虚拟机的类加载机制. 类加载的时机 一个类型 ...
- 组合注解(Annotation)
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.an ...
- unable to load script from assets 'index.android bundle'
在Android手机上运行React-native项目时 报错:unable to load script from assets 'index.android bundle' ,make sure ...
- CSS DIV中表格居中显示
将div的text-align设为center,然后将table的margin设为auto,即: <div> <table style="margin:auto; widt ...
- 前端日常工作中常用开发小技巧 ---JavaScript
1.格式化金钱值 const ThousandNum = num => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "," ...
- Oracle 11g各种服务作用以及哪些需要开启
Windwos server 2012 R2上成功安装Oracle 11g后共有7个服务,如果全局数据库名为orcl,则Oracle服务分别为 Oracle ORCL VSSWriter Servic ...
- hive命令查询数据不显示表头解决办法
在hive命令行中查询数据如下: 表头未显示出来 解决办法: 修改hive安装包conf/hive-site.xml配置文件: <property> <name>hive.cl ...