题目

P4965 薇尔莉特的打字机

快到十二点了正在颓废突然发现了一道好题

虽然毒瘤,但确实是容斥原理的好题啊,做法也特别巧妙(标程

思路

题目大意(怕自己突然忘)

n个初始字符,m个操作(加入或删除),任何一个操作都可能无效,求最后不同的字符方案数\((n,m<=5*10^6)\)

先考虑无删除操作

这里的\(t_{0..i}\)为一个字串,\(\widetilde{t_{0..i}}\)指该字串不同的子序列个数,\(dp_i\)为\(\widetilde{t_{0..i-1}}\)

若\(t_{i}\)这个字符在循环时第一次出现,即\(t_{0...i-1}\)没出现过\(t_{i}\),显然我们考虑的状态有三种

\(~~~~~1.\widetilde{t_{0..i-1}}\),有 \(dp_{i-1}\)个\(\Longrightarrow\)理解:插入操作无效或只考虑前面字符的方案数

\(~~~~~2.\widetilde{t_{0..i-1}} + \{t_i\}\),有\(dp_{i-1}\)个\(\Longrightarrow\)理解:插入操作有效,且与前面字符组合起来的方案数

\(~~~~~3.\widetilde{t_{i..i}}\)\(\Longrightarrow\)理解:插入操作有效\(t_{i}\)单独组成一种方案

综上,\(t_{i}\)这个字符在循环时第一次出现:\(dp_{i}=2*dp{i-1}+1\)

\(\begin{aligned}
\\
\end{aligned}\)

那不是第一次出现呢?显然会出现重复的子序列

\(lst[c]\)表示字符\(c\) 上一次出现的位置

1.\(\widetilde{t_{0..lst[t_i]-1}}+\{t_{lst[t_i]}\}\)与\(\widetilde{t_{0..lst[t_i]-1}}+\{t_i\}\) 重复

2.\(\{t_{lst[t_i]}\}\) 与 \(\{t_i\}\) 重复

综上,\(dp_i\)要去掉\(dp_{lst[t_i]-1}+1\)

\(\therefore dp_i=\begin{cases}2*dp_{i-1}+1\quad(t_i\text{第一次出现})\\2dp_{i-1}-dp_{lst[t_i]-1}\quad (t_i\text{出现过})\end{cases}\)

目前为止,时间复杂度为\(O(m)\),毒瘤的出题人不可能就这样放过我们嘛\(emmm\)

考虑删除操作

其实删除操作只用考虑删除前面的文本串,为什么?删除插入操作无异与:删除与插入两个操作同时无效,而前面的方程已经将此情况考虑进去了

故我们只用考虑文本串与插入操作中间的删除操作

当能作为有效删除操作为\(cnt\)个时,我们枚举有\(k(k<=cnt)\)个有效操作

则此时新增子序列\(s_{0..n-k-1} + \widetilde{t_{pre[p_k]..m-1}}\)

发现没有?从小到大枚举\(k\),时间复杂度瞬间指数加\(1\)成了\(O(m^2)\),那我们就从\(m-1\)~\(0\)逆推,又变成线性的了!!

故\(dp_i\)为\(\widetilde{t_{i..m-1}}\),\(lst[c]\)为倒推时字符\(c\)上一次出现的位置,由于删除操作的存在,方程中的\(dp_{i-1}\) 改为\(dp_{pre[i]}\)(这些应该都好理解吧)

\(\begin{aligned}
\\
\end{aligned}\)

同样地,我们还得考虑重复部分,

若退格所删去的最后一个字符即\(s_{n-k}\)在 \(t_{pre[p_k]..m-1}\) 中出现过,则会产生重复的答案:第\(k\)删除在文本串\(s\)中删除的字符是\(s_{n-k}\),

而在第\(k-1\) 个删除 时,\(s_{n-k}\)不会被删除,则一旦 \(s_{n-k}\) 在 \(t_{pre[p_k]..m-1}\) 中出现过,就意味着在只有\(k-1\)个删除时\(s_{n-k}\)会与后面的发生重复

重复子序列为\(s_{0..n-k}+\widetilde{t_{pre[lst[s_{n-k}]]..m-1}}\)以及\(s_{0..n-k}\),个数为 \(dp_{pre[lst[s_{n-k}]]}+1\),计算答案时要将这部分减去

My complete code

上短得可怜的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int p=0x125E591;
const int maxn=5000000+9;
int n,m,pos,cnt,ans;
int lst[maxn],pre[maxn],dp[maxn];
char s[maxn],t[maxn];
inline int Get(char x){
return (lst[x])?p-dp[pre[lst[x]]]:1;
}
int main(){
scanf("%d%d",&n,&m);
scanf(" %s %s",s,t);
for(int i=0;i<m;++i)
cnt+=(t[i]=='u');
for(int i=m-1;i>=0;--i)
if(t[i]=='u'){
if(n-cnt>=0)
ans=(ans+dp[pos]+Get(s[n-cnt]))%p;
--cnt;
}else{
dp[i]=(2*dp[pre[i]=pos]+Get(t[i]))%p;
pos=lst[t[i]]=i;
}
printf("%d",(ans+dp[pos]+1)%p);
return 0;
}

总结

动规啊容斥啊这些真的得完全弄懂再去写代码,几次想写代码了还是回过头自己纯手推了一下

能想到写篇博客竟然花了快一个多小时,凌晨一点半 其实也还早啊,睡觉

P4965 薇尔莉特的打字机的更多相关文章

  1. 洛谷4965 薇尔莉特的打字机(Trie,DP)

    神仙题. 考虑在一棵 Trie 上进行染色,将可能出现的串的末尾染成黑色.答案就是黑点的个数.一开始只有 \(A\) 的末尾点是黑色. 当出现一个字符(不是退格)\(c\) 时,就要将每个黑点的 \( ...

  2. ACM训练联盟周赛(第一场)

    B:Zeratul与Xor 题目描述 Xor(按位异或),对应C++中的“^”运算符. Zeratul给出了一个数列A[n](n≤105),要做q(q≤105)组动作,这些动作包括: 1  a:数列中 ...

  3. 【胡策篇】题解 (UOJ 192 + CF938G + SPOJ DIVCNT2)

    和泉纱雾与烟花大会 题目来源: UOJ 192 最强跳蚤 (只改了数据范围) 官方题解: 在这里哦~(说的很详细了 我都没啥好说的了) 题目大意: 求树上各边权乘积是完全平方数的路径数量. 这种从\( ...

  4. Python语言之面向对象

    Python语言之面向对象 前言 面向对象 -- Object Oriented 简写:OO 面向对象设计 -- Object Oriented Design 简写:OOD 面向对象编程 -- Obj ...

  5. 小贝_mysql select连接查询

    select连接查询 简要: 一.union联合查询 二.左右内连接 一.union联合查询 作用: 把2次或多次查询结果合并起来 具体: (表1查询结果) union (表2查询结果) 运行: 先算 ...

  6. 营口6378.7939(薇)xiaojie:营口哪里有xiaomei

    营口哪里有小姐服务大保健[微信:6378.7939倩儿小妹[营口叫小姐服务√o服务微信:6378.7939倩儿小妹[营口叫小姐服务][十微信:6378.7939倩儿小妹][营口叫小姐包夜服务][十微信 ...

  7. 本溪6397.7539(薇)xiaojie:本溪哪里有xiaomei

    本溪哪里有小姐服务大保健[微信:6397.7539倩儿小妹[本溪叫小姐服务√o服务微信:6397.7539倩儿小妹[本溪叫小姐服务][十微信:6397.7539倩儿小妹][本溪叫小姐包夜服务][十微信 ...

  8. FreeBSD基金会添加新成员,梁莉成为第一位来自微软和中国的基金会董事

    这个月23日FreeBSD基金会很高兴地宣布Philip Paeps和Kylie Liang (梁莉)正式加入董事会. 梁莉,现任微软开源技术部高级项目经理,主要负责FreeBSD在公有云以及私有云的 ...

  9. 【爆料】-《英博夏尔大学毕业证书》BPP一模一样原件

    英博夏尔大学毕业证[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归&a ...

随机推荐

  1. full join 时通过辅助列序号列消除笛卡尔积重复列

    如果没有序号列,那么如果领灯表里有3条数据,还灯表里面有2条数据,full join后就是3*2=6条数据 --1.领灯表,每天每班每人允许重复数据 select ID ,ROW_NUMBER() o ...

  2. WCF获取元数据

    所谓获取WCF的服务元数据(Metadata),归根结点,实际上就是获取服务的终结点(Endpoint)的信息,这是服务公开在外的数据信息,包括Address.Binding与Contract,也就是 ...

  3. tcpdump command

    工作中一直在用tcpdump,感觉非常方便,今天心血来潮百度了一下tcpdump的用法,才发现原来还有这么多强大的功能自己都不知道,那叫一个汗啊. 以此文作为备份,记录一些新知道的用法,各位网友谁有新 ...

  4. Struts2学习之拦截器栈

    © 版权声明:本文为博主原创文章,转载请注明出处 拦截器栈: - 从结构上看:拦截器栈相当于多个拦截器的组合 - 从功能上看:拦截器栈也是拦截器 默认拦截器栈: - 在struts-core.jar中 ...

  5. atitit.基于bat cli的插件管理系统.doc

    atitit.基于bat cli的插件管理系统.doc /AtiPlatf/src_atibrow/com/attilax/cmd/CmdX.java pathx.isWebPathMode=true ...

  6. Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结

    Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结 1.1. Java的编年史2 ...

  7. SPI协议介绍

    一.概述 SPI, Serial Perripheral Interface, 串行外围设备接口, 是 Motorola 公司推出的一种同步串行接口技术. SPI 总线在物理上是通过接在外围设备微控制 ...

  8. CentOS: Make Command not Found and linux xinetd 服务不能启动

    在centos 安装编译器 yum -y install gcc automake autoconf libtool make linux xinetd 服务不能启动: [root@capaa xin ...

  9. #define的使用方法体会

    #define 创建一个宏,该宏是标识符或參数化标识符与标记字符串的关联. 在定义宏之后.编译器可用标记字符串替换源文件里标识符的每一个匹配项. 双击以所有折叠.">语法 #defin ...

  10. [转]maven2中snapshot快照库和release发布库的应用

    [转载声明] 转载时必须标注:本文来源于铁木箱子的博客http://www.mzone.cc [原文地址] 原文永久地址是:http://www.mzone.cc/article/279.html 在 ...