跳表上线性dp——1150D 好题!
题目设计的很好,感觉做了这题对dp的状态有了更深的理解
/*
先预处理序列自动机
dp[i][j][k]表示匹配到i,j,k时的最靠前的位置
那么现在A串加入了一个字母,我们要求的就是dp[i+1][j][k]
根据dp的状态转移
因为 dp[i][j][k]之前的状态已经全部确定下来,
所以只要在i+1的状态下枚举两重循环jk即可
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
char s[maxn];
int n,pos[],q,nxt[maxn][];
void init(){
for(int i=;i<;i++)pos[i]=n+;
for(int i=n;i>=;i--){
for(int j=;j<;j++)
nxt[i][j]=pos[j];
pos[s[i]-'a']=i;
}
for(int i=;i<;i++)
nxt[n+][i]=n+;
} int A,B,C,dp[][][];
char a[maxn],b[maxn],c[maxn];
int main(){
scanf("%d%d%s",&n,&q,s+);
init();
char op[],ch[];int p;
while(q--){
cin>>op>>p;
if(op[]=='-'){
if(p==)A--;if(p==)B--;if(p==)C--;
}
else {
cin>>ch;
if(p==){//带A的所有新状态
a[++A]=ch[];
for(int j=;j<=B;j++)
for(int k=;k<=C;k++)
dp[A][j][k]=n+;
for(int j=;j<=B;j++)
for(int k=;k<=C;k++){
dp[A][j][k]=min(dp[A][j][k],nxt[dp[A-][j][k]][a[A]-'a']);
if(j)dp[A][j][k]=min(dp[A][j][k],nxt[dp[A][j-][k]][b[j]-'a']);
if(k)dp[A][j][k]=min(dp[A][j][k],nxt[dp[A][j][k-]][c[k]-'a']);
//cout<<dp[A][j][k]<<'\n';
}
} if(p==){
b[++B]=ch[];
for(int i=;i<=A;i++)
for(int k=;k<=C;k++)
dp[i][B][k]=n+;
for(int i=;i<=A;i++)
for(int k=;k<=C;k++){
dp[i][B][k]=min(dp[i][B][k],nxt[dp[i][B-][k]][b[B]-'a']);
if(i)dp[i][B][k]=min(dp[i][B][k],nxt[dp[i-][B][k]][a[i]-'a']);
if(k)dp[i][B][k]=min(dp[i][B][k],nxt[dp[i][B][k-]][c[k]-'a']);
}
} if(p==){
c[++C]=ch[];
for(int i=;i<=A;i++)
for(int j=;j<=B;j++)
dp[i][j][C]=n+;
for(int i=;i<=A;i++)
for(int j=;j<=B;j++){
dp[i][j][C]=min(dp[i][j][C],nxt[dp[i][j][C-]][c[C]-'a']);
if(i)dp[i][j][C]=min(dp[i][j][C],nxt[dp[i-][j][C]][a[i]-'a']);
if(j)dp[i][j][C]=min(dp[i][j][C],nxt[dp[i][j-][C]][b[j]-'a']);
}
}
}
// cout<<dp[A][B][C]<<'\n';
if(dp[A][B][C]!=n+)puts("YES");
else puts("NO");
}
}
跳表上线性dp——1150D 好题!的更多相关文章
- 线性dp——cf1012C好题
比较套路的dp题 /* dp[i][j][0|1]:前i座山盖了j座房子,第i座不盖|盖 dp[i][j][0]=min( dp[i-1][j][0] , dp[i-1][j][1]+max(0,a[ ...
- zoj4027 线性dp!好题
非常好的dp,可是我太菜做不出来.. /* 第i个左括号不可能越过第i+1个左括号 如果第i个左括号到位置j,前提是第i+1个左括号就必须到位置j+1即以后 用dp[i][j]表示把第i个左括号转移到 ...
- 单调队列+线性dp题Watching Fireworks is Fun (CF372C)
一.Watching Fireworks is Fun(紫题) 题目:一个城镇有n个区域,从左到右1编号为n,每个区域之间距离1个单位距离节日中有m个烟火要放,给定放的地点ai,时间ti当时你在x,那 ...
- [线性DP][codeforces-1110D.Jongmah]一道花里胡哨的DP题
题目来源: Codeforces - 1110D 题意:你有n张牌(1,2,3,...,m)你要尽可能多的打出[x,x+1,x+2] 或者[x,x,x]的牌型,问最多能打出多少种牌 思路: 1.三组[ ...
- lettcode 上的几道哈希表与链表组合的数据结构题
目录 LRU缓存 LFU缓存 全O(1)的数据结构 lettcode 上的几道哈希表与链表组合的数据结构题 下面这几道题都要求在O(1)时间内完成每种操作. LRU缓存 LRU是Least Recen ...
- cf909C 线性dp+滚动数组好题!
一开始一直以为是区间dp.. /* f下面必须有一个s 其余的s可以和任意f进行匹配 所以用线性dp来做 先预处理一下: fffssfsfs==>3 0 1 1 dp[i][j] 表示第i行缩进 ...
- Nowcoder Removal ( 字符串上的线性 DP )
题目链接 题意 : 给出长度为 n 的字符串.问你准确删除 m 个元素之后.能产生多少种不同的子串 分析 ( 参考博客 ): 可以考虑线性 DP 解决这个问题 试着如下定义动态规划数组 dp[i][ ...
- 线性dp
线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...
- 机器分配----线性dp难题(对于我来说)
题目: 总公司拥有高效设备M台, 准备分给下属的N个分公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值.其中M <= 15, ...
随机推荐
- chomp
用来除去最后的换行等空白字符. 例程: #!/usr/bin/perl #chomp.pl use warnings; use strict; print "Input a string & ...
- 关于a[::-1]
b = a[i:j] 表示复制a[i]到a[j-1],以生成新的list对象,a[:]就相当于完整复制一份a b = a[i:j:s]表示:i,j与上面的一样,但s表示步进,缺省为1.即从i到j每 ...
- Python3中string内置参数
说明: 使用ipython查看python3的内置函数 ,只需要输入字符串按两下tab键 capitalize():将字符串中第一个字符大写 casefold:将字符串中的所有大写字母转为小写 cen ...
- <读书笔记>001-以解决问题为导向的python编程实践
以解决问题为导向的python编程实践 0.第0章:计算机科学 思考:计算机科学是否为计算机编程的简称? 编程的困难点:1.同时做2件事(编程语言的语法.语义+利用其解决问题) 2.什么是好程序(解 ...
- 【LGP5439】【XR-2】永恒
题目 是个傻题 显然枚举每一条路径经过了多少次,如果\(u,v\)在树上不是祖先关系的话经过\((u,v)\)这条路径的路径条数就是\(sum_u\times sum_v\) 于是我们子树大小映射到\ ...
- 初探.Net Core API 网关Ocelot(一)
一.介绍 Ocelot 是基于.NetCore实现的开源的API网关,支持IdentityServer认证.Ocelot具有路由.请求聚合.服务发现.认证.鉴权.限流熔断等功能,并内置了负载均衡器与S ...
- 2018自己的JavaScript开发指南
这是一个备忘清单,可以让你在不用做太多选择的情况下快速学习.我会列出一些工具来满足大部分场景下的前端开发.当你看完这篇文章,你会有足够的自信来调整你的技术栈. ☉概要 我会将地图划分为你需要解决的问题 ...
- Git查看历史记录的几种方法
- 2019-7-29-C#-在基类定义好方法让子类继承接口就能实现
title author date CreateTime categories C# 在基类定义好方法让子类继承接口就能实现 lindexi 2019-07-29 09:57:49 +0800 201 ...
- Spark SQL设计