博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2553 禁忌
阅读量:5216 次
发布时间:2019-06-14

本文共 1344 字,大约阅读时间需要 4 分钟。

首先我们要考虑给定一个串,如何将他划分,使得他有最多的禁忌串

我们只需要按里面出现的禁忌串们的出现的右端点排序然后贪心就可以啦

我们建出AC自动机,在AC自动机等价于走到一个包含禁忌串的节点就划分出一段

那么不妨设f(i,j)表示走了i步当前在AC自动机的j节点上

这样的DP方程跟BZOJ 1030是类似的

但是由于i可能会很大,但是j是很小的,又因为每一步的转移都是一样的

所以我们可以考虑矩阵乘法来优化DP

可是当我们用AC自动机构建了转移矩阵之后,我们会发现我们没办法算答案

我们只能算经过L步到达AC自动机某节点的概率

那么我们不妨新建节点表示答案,在每次出现禁忌串的时候在新建节点上贡献相应的期望

同时新建节点要将上次贡献得到的期望传递给下一次的转移

所以矩阵中n->n存在转移

 

值得一提的是:这个题目卡精度,我一开始写的double,结果WA了

去网上看了看题解之后默默的改成了long double,然后A了

#include
#include
#include
#include
#include
#include
using namespace std; const int maxn=102;int n,L,k,cnt;bool vis[maxn];char s[maxn];int t[maxn][26];int fail[maxn];bool end[maxn];struct Matrix{ long double a[maxn][maxn]; Matrix(){memset(a,0,sizeof(a));}}A,ans;queue
Q; void insert(){ scanf("%s",s+1); int len=strlen(s+1),now=1; for(int i=1;i<=len;++i){ int id=s[i]-'a'; if(!t[now][id])t[now][id]=++cnt; now=t[now][id]; }end[now]=true;}void build_fail(){ Q.push(1);fail[1]=0; while(!Q.empty()){ int u=Q.front();Q.pop(); end[u]|=end[fail[u]]; for(int i=0;i
>=1; }return tmp;} int main(){ scanf("%d%d%d",&n,&L,&k);cnt=1; for(int i=1;i<=n;++i)insert(); n=cnt+1; build_fail();build_Matrix(); ans=pow_mod(L); printf("%.7lf\n",(double)(ans.a[1][n])); return 0;}

  

转载于:https://www.cnblogs.com/joyouth/p/5366399.html

你可能感兴趣的文章
Maximum Product Subarray
查看>>
solr相关配置翻译
查看>>
通过beego快速创建一个Restful风格API项目及API文档自动化(转)
查看>>
解决DataSnap支持的Tcp长连接数受限的两种方法
查看>>
Synchronous/Asynchronous:任务的同步异步,以及asynchronous callback异步回调
查看>>
ASP.NET MVC5 高级编程-学习日记-第二章 控制器
查看>>
Hibernate中inverse="true"的理解
查看>>
高级滤波
查看>>
使用arcpy添加grb2数据到镶嵌数据集中
查看>>
[转载] MySQL的四种事务隔离级别
查看>>
QT文件读写
查看>>
C语言小项目-火车票订票系统
查看>>
15.210控制台故障分析(解决问题的思路)
查看>>
BS调用本地应用程序的步骤
查看>>
常用到的多种锁(随时可能修改)
查看>>
用UL标签+CSS实现的柱状图
查看>>
mfc Edit控件属性
查看>>
Linq使用Join/在Razor中两次反射取属性值
查看>>
[Linux]PHP-FPM与NGINX的两种通讯方式
查看>>
Java实现二分查找
查看>>