【NOIP2015提高组】子串 区间DP+滚动数组优化

题意:

有两个仅包含小写英文字母的字符串 A 和 B。

现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的字符串。

请问有多少种方案可以使得这个新串与字符串 B 相等?

注意:子串取出的位置不同也认为是不同的方案。

 

数据范围:

对于第 1 组数据:1≤n≤500,1≤m≤50,k=1;
对于第 2 组至第 3 组数据:1≤n≤500,1≤m≤50,k=2
对于第 4 组至第 5 组数据:1≤n≤500,1≤m≤50,k=m
对于第 1 组至第 7 组数据:1≤n≤500,1≤m≤50,1≤k≤m
对于第 1 组至第 9 组数据:1≤n≤1000,1≤m≤100,1≤k≤m
对于所有 10 组数据:1≤n≤1000,1≤m≤200,1≤k≤m

------------------------------------------------------我是分割线----------------------------------------------------

题解:一道状态不太明显的题,我们首先要寻找这道题的切入点。

观察这道题的特点,我们发现,相对于B,A中的每个字符显然有选与不选两种决策。

而对于这两个字符串,可以用两个指针表示,一个指向A的状态,一个指向B的状态。

于是这道题的状态就很被发现了。

设置状态:

设 F(i,j,k,1) 表示A的前i个字符中,匹配到B中当前第j个字符,一共使用了k段,选择当前第i个字符的方案数。

F(i,j,k,0)  表示A的前i个字符中,匹配到B中当前第j个字符,一共使用了k段,不选择当前第i个字符的方案数。

然后就是状态转移:

由状态,我们可以推出如下状态转移方程:

(1) 当Ai == Bj 时,F(i,j,k,0) = F(i-1,j,k,0)+ F(i-1,j,k,1).

     即当前A中第i个数不作为答案的方案数 == 前i-1的方案数总和。

           F(i,j,k,1) = F(i-1,j-1,k-1,0) + F(i-1,j-1,k-1,1) + F(i-1,j-1,k,1);

     即当前A中第i个数作为答案的方案数 == A中前i-1个数匹配到B中第j-1个的方案数总和(i不接到前一个答案中) + A中前i-1个数方案(i接到前一个答案中)。  

(2)当Ai  != Bj 时, F(i,j,k,0) = F(i-1,j-1,k,0) + F(i-1,j-1,k,1).

             同(1)中的转移。

           F(i,j,k,1) = 0;  

          由于当前数不能作为答案,所以方案为0.

再确定边界条件,我们可以知道,F(i,0,0,0) = 1;即匹配B中0个字符的方案为1.

于是我们可以写出代码:

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int mod = 1e9+7;
const int N = 1e6 + 50;
int n, m, p;
int f[1010][101][101][2];
char a[N], b[N];
inline int read() {int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void work(){rep(i, 0, n) f[i][0][0][0] = 1;rep(i, 1, n) rep(j, 1, m) rep(k, 1, p){if(a[i] == b[j]) {f[i][j][k][0] = (f[i-1][j][k][0] + f[i-1][j][k][1])%mod;f[i][j][k][1] = (f[i-1][j-1][k-1][0] + (f[i-1][j-1][k-1][1] + f[i-1][j-1][k][1]) % mod) % mod;}else {f[i][j][k][1] = 0;f[i][j][k][0] = (f[i-1][j][k][0] + f[i-1][j][k][1])%mod;}}printf("%d\n", (f[n][m][p][1] + f[n][m][p][0])%mod); 
}
void init(){n = read(); m = read(); p = read();scanf("%s%s", a+1, b+1);
}
int main(){init(); work();return 0;
}
View Code

但是我们发现,这份代码空间复杂度效率低下(2*n*m*k),无法通过此题,我们还需要优化。

于是乎,DP常用的空间优化:滚动数组优化就出现了。

观察DP转移方程,我们可以发现,每一个决策i只与前一个决策i-1有关,其他的空间都是多余的。

所以我们就可以用01方法表示。

AC代码如下:

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int mod = 1e9 + 7;
const int N = 1e6 + 50;
int n, m, p;
int f[2][220][220][2];
char a[N], b[N];
inline int read() {int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void work(){int val = 1;f[0][0][0][0] = f[1][0][0][0] = 1; rep(i, 1, n) {rep(j, 1, m) rep(k, 1, p){if(a[i] == b[j]) {f[val][j][k][0] = (f[val^1][j][k][0] + f[val^1][j][k][1])%mod;f[val][j][k][1] = (f[val^1][j-1][k-1][0] + (f[val^1][j-1][k-1][1] + f[val^1][j-1][k][1]) % mod) % mod;}else {f[val][j][k][1] = 0;f[val][j][k][0] = (f[val^1][j][k][0] + f[val^1][j][k][1])%mod;}}val ^= 1;}printf("%d\n", (f[n&1][m][p][1] + f[n&1][m][p][0])%mod); 
}
void init(){n = read(); m = read(); p = read();scanf("%s%s", a+1, b+1);
}
int main(){init(); work();return 0;
}
View Code

总结:这道题作为线性DP的练习题(NOIP的题),有一定的思维难度,对DP思维提升有很大的帮助。

转载于:https://www.cnblogs.com/smilke/p/11587313.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/549468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

教你如何去淘便宜机票

机票四月二十日集体变相涨价后&#xff0c;中央电视台曾经报道&#xff0c;今后没有5折以下机票&#xff0c;今后也不再叫多少折&#xff0c;而是直接报价&#xff0c;但是春秋航空不再此之列&#xff0c;原因是这次变相提价是一个叫中航信公司在操作&#xff0c;他们不代理春秋…

使用kibana或postman操作Elasticsearch的常用命令

前言服务器&#xff1a;CentOS-6.7 运行系统&#xff1a;windows10 JDK版本&#xff1a;1.8 Elasticsearch版本&#xff1a;5.6.6 插件&#xff1a;kibana、elasticsearch-head 工具&#xff1a;postman 一、集群查看集群是否健康 GET /_cluster/health二、节点查看节点列表后面…

asp.net 实现一级域名与二级域名共享COOKIE

COOKIE可以自动由子级域名分享&#xff0c;无须做什么特别设置。对网站www.abc.com&#xff0c;check.abc.com来说&#xff0c;它们都是二级域名&#xff0c;一级域名是abc.com。所以&#xff0c;保存COOKIE的时候&#xff0c;将Cookie的Domain设置成“.abc.com”&#xff0c;无…

32位单精度浮点乘法器的FPGA实现

摘 要: 采用Verilog HDL语言, 在FPGA上实现了32位单精度浮点乘法器的设计, 通过采用改进型Booth编码&#xff0c;和Wallace 树结构, 提高了乘法器的速度。本文使用Altera Quartus II 4.1仿真软件, 采用的器件是EPF10K100EQ 240 -1, 对乘法器进行了波形仿真, 并采用0.5CMOS工艺…

Elasticsearch修改字段之别名,扩展数据迁移

https://blog.csdn.net/amaranth__/article/details/84497075 转载于:https://www.cnblogs.com/zeenzhou/p/11588599.html

网工视频13第13章.计算机系统开发运行与配置疑难问题

网工视频请留下你的邮箱&#xff0c;我给你发邮件。转载于:https://blog.51cto.com/ricebetter2010/155609

ES 基本操作

0.查看集群是否健康GET /_cluster/health 1.查询所有索引GET /_cat/indices?v 2.查询单个索引的映射GET /index_trans_detail/_mapping 3.删除indexDELETE /index_trans_detail,index_two 4. 添加字段映射PUT /index_trans_detail/_mapping/type_trans_detail{ "properti…

我们的运动会

不久前&#xff0c;我们举办了微软中国研发集团的首届运动会。遗憾的是&#xff0c;当时我自己由于公务在身没能参加。事后同事们把许多精彩的图片与我分享&#xff0c;让我十分羡慕他们有机会大显身手&#xff0c;现在贴出来让大家看看他们的飒爽英姿&#xff0c;一睹为快。运…

ES建立索引步骤, 1,index 2.mapping 3,别名

1.建立索引PUT /index_trans_detail 2.建立mappingPOST /index_trans_detail/type_trans_detail/_mapping{ "type_trans_detail": { "properties": { "id": { "type": "long" }, "entId": { "type": &q…

java路径问题

Java路径 Java中使用的路径&#xff0c;分为两种&#xff1a;绝对路径和相对路径。具体而言&#xff0c;又分为四种&#xff1a; 一、URI形式的绝对资源路径 如&#xff1a;file:/D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b URL是URI的特例。URL的前缀/协议&#xff0c;…

题解P1613跑路

今天没什么好说的那我就卖个萌吧(&#xff5e;&#xffe3;▽&#xffe3;)&#xff5e; Luogu 一道思维题可能仅是对我来说&#xff0c;对于大佬们都是显然的 简化题意 给你一个图&#xff0c;找到一个路径&#xff0c;使其路径的二进制位中\(1\)的个数最少 分析 这题的题目就…

路由重分布列表控制例子

OSPF与RIP路由重分布配置&#xff0c;使用重分布列表&#xff0c;对分布的路由进行控制的配置如上例图所示&#xff1a;“RIP与OSPF路由重分布例子”switchA(config)#router ripswitchA(config-router)#network 192.168.10.0switchA(config-router)#network 192.168.20.0switch…

git随笔

repo init -u ssh://wangxygit.fd565.com:29418/Product/F3/Lichee.git rm .repo/ -rf rm ~/.ssh/* -rf ssh-keygen cat ~/.ssh/id_rsa.pu repo sync -j8 —————————————————————————————————————————————————————————…

F#入门书籍

作为 Microsoft .NET Framework 家族的新成员&#xff0c;F# 提供类型安全、性能以及类似脚本语言的工作能力&#xff0c;所有这些都是 .NET 环境的一部分。此函数式语言由 Microsoft 研究院的 Don Syme 发明&#xff0c;作为 CLR 的 OCaml 语法兼容变体&#xff0c;但 F# 已经…

OCP-052考试题库汇总(59)-CUUG内部解答版

In one of your databases: 1.USER1 and USER2 have no system privileges. 2.ROLE1 only has these privileges: ?CREATE SESSION ?CREATE TABLE ?CREATE VIEW Examine these commands: SQL> conn / as sysdba Connected. SQL> GRANT create table, role1 TO user1 W…

性能测试工具SilkPerformer介绍

SilkPerformer 是业界最强大&#xff0c;且最易用的企业级负载和强度测试解决方案&#xff0c;用于对关键任务应用的质量进行优化。SilkPerformer使用可视化脚本生成技术和对存在成千上万的并发用户的多个应用环境进行测试的能力&#xff0c;使您能够在企业应用部署之前&#x…

题解P3745期末考试

我太菜了&#xff0c;QAQ Luogu 简要分析 和洛谷的一篇分治的题解是一样的想法&#xff08;是我看的她的&#xff09;&#xff0c;我只是一个更详细的代码解释&#xff0c;所以大家还是看洛谷题解吧 简要说一下。贪心的选取。在C花费多的情况下&#xff0c;若A比B花费多&#x…

pluto实现分析(22)

本文档的Copyleft归yfydz所有&#xff0c;使用GPL发布&#xff0c;可以自由拷贝&#xff0c;转载&#xff0c;转载时请保持文档的完整性&#xff0c;严禁用于任何商业用途。msn: yfydz_no1hotmail.com来源&#xff1a;http://yfydz.cublog.cn18. 密钥处理pluto的配置文件中支持…

OCP-052考试题库汇总(60)-CUUG内部解答版

Examine these facts about a database: The database default tablespace to EXAMPLE. DEFERRED_SEGMENT_CREATION is TRUE (原来为 FALSE&#xff0c;题目有错) Examine these commands: SQL> CREATE USER user1 IDENTIFIED BY oracle_4U PASSWORD EXPIRE; User created. …

JavaScript tips and tricks - 4

JavaScript doesn’t have block scopeBlock doesn’t have scope in javascript, only function has scope. for(var i 0; i < 2; i ) { } i; // 2 If you want to create scope, use anonymous function: (function (){ for(var i 0; i < 2; i ) { } })(); typeof(i…