首页 > 其他分享 >luogu2516题解

luogu2516题解

时间:2024-09-10 18:16:43浏览次数:11  
标签:luogu2516 题解 sum dp s2 fi s1 se

随机说话

第一次交的时候写的版本是这个
下面在 sum 的计算上少了个 else,遂出错。
以后写的时候还是尽量简单点,主要是调试的时候好调。

题目分析

题目里面的公共子序列就是可以不连续可以为空的在字符串里出现顺序相同的子串。

对于一个公共子序列,在找到最后一个公共的字符的时候,是由前面的公共子序列转移过来的。

对于两个字符串前面的子串求出的所有公共子序列,我们发现长度不是最大的公共子序列对答案没有贡献,所以没有必要转移其他长度的公共子序列的个数。

循环枚举的过程中我们的求解过程是有从字符串前到字符串后的顺序的,在状态转移的过程中不能忽略这个字符串位置对状态转移的影响。

在循环枚举两个字符串 \(s1,s2\) 位置 \(s1_i,s2_j\) 的时候,我们发现公共子序列所取字符的位置对答案没有贡献,故也可从状态中省去。

我们令 \(dp_j\) 为以 \(s1_i,s2_j\) 结尾的最长公共子序列的状态(包括最长长度和个数),在枚举到 \(s1_i,s2_j\) 的时候 \(dp_{i,j}=\{\max(dp_{i-1,l}.len(l\in\left[1,j\right)))+1,\sum\limits_{dp_{i-1,k}=\max(dp_{i-1,l}(l\in\left[1,j\right)))}dp_{i-1,k}.cnt\}\),这样就可以求出此题的答案。

由于一维可以省去,故用了类似完全背包的方法倒着跑来省下内存。

在求解中间和的过程可以像前缀和一样预处理一下,使时间复杂度由 \(O(n^3)\) 变为 \(O(n^2)\)。

代码如下。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
constexpr int MOD=1e8,MAXN=5000+10;
char s1[MAXN],s2[MAXN];
int n1,n2;
pii sum[MAXN],dp[MAXN];//fi=len,se=cnt
#define fi first
#define se second
int main(){
	scanf("%s%s",s1+1,s2+1);
	n1=strlen(s1+1);
	n2=strlen(s2+1);
	sum[0]={0,1};
	for(int i=1;i<=n1;++i){
		for(int j=1;j<=n2;++j){
			if(dp[j].fi>sum[j-1].fi){
				sum[j]=dp[j];
			}else if(dp[j].fi==sum[j-1].fi){
				sum[j].fi=sum[j-1].fi;
				sum[j].se=(sum[j-1].se+dp[j].se)%MOD;
			}else{
				sum[j]=sum[j-1];
			}
		}
		for(int j=n2;j;--j){
			if(s1[i]==s2[j]){
				if(sum[j-1].fi+1>dp[j].fi){
					dp[j].fi=sum[j-1].fi+1;
					dp[j].se=sum[j-1].se;
				}else if(dp[j].fi==sum[j-1].fi+1){
					dp[j].se=(dp[j].se+sum[j-1].se)%MOD;
				}
			}
		}
	}
	printf("%d\n%d\n",dp[n2].fi-1,dp[n2].se);
	return 0;
} 

标签:luogu2516,题解,sum,dp,s2,fi,s1,se
From: https://www.cnblogs.com/LiJoQiao/p/18406891

相关文章

  • P4563 [JXOI2018] 守卫 题解
    P4563[JXOI2018]守卫题解不愧是九条可怜的\(\text{JXOI}\),只能说确实是道好题。假设当前我们在求\([l,r]\),我们不难发现\(r\)端点一定要放保镖,于是考虑\(r\)保镖的最大监视范围\([x,r]\)。由题意得到对于\([x,r]\)中的每个\(p_1,p_2,\cdots,p_k\),要求斜率\(t(p_i,......
  • 树上一些点的选 题解
    题意简述给你一棵\(n\)个节点以\(1\)为根的有根树,和一个整数\(m\)。对于树上每一个点\(u\),有三个权值\(X,Y,Z\)。你需要在\(u\)的祖先里(不含\(u\))中选出至少\(X\)个点,记\(S_1\)表示这些点到\(u\)的距离之和;在\(u\)的后代里(不含\(u\))中选出至少\(Y\)个点,......
  • CF717A Festival Organization 题解
    Description一个合法的串定义为:长度在\([l,r]\)之间,且只含0,1,并且不存在连续\(2\)个或更多的\(0\)。现在要选出\(k\)个长度相同的合法的串,问有几种选法,答案模\(10^9+7\)。\(1\leqk\leq200,1\leql\leqr\leq10^{18}\)。Solution容易发现答案为\(\sum_{i=l+2}^{r......
  • 【Py/Java/C++三种语言OD独家2024E卷真题】20天拿下华为OD笔试之【回溯】2024E-字符串
    可上欧弟OJ系统练习华子OD、大厂真题绿色聊天软件戳od1441了解算法冲刺训练(备注【CSDN】否则不通过)文章目录相关推荐阅读题目描述与示例题目描述输入描述输出描述示例一输入输出说明示例二输入输出说明解题思路代码pythonjavacpp时空复杂度华为OD算法/大厂面......
  • Android中SurfaceView的双缓冲机制和普通View叠加问题解决办法
    本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点SurfaceView是Android平台上用于高效渲染图形的视图控件。它将内容绘制在一个独立的Surface上,可以直接由渲染线程访问,从而提高性能,尤其是在需要频繁刷新和更新......
  • 题解:CF913C Party Lemonade
    分析因为容量为\(2^{i-1}\),所以对于任意的\(i<j\),第\(j\)种瓶子一定可以通过选择\(2^{j-i}\)个\(i\)种瓶子来实现。定义一个瓶子的性价比为\(\dfrac{\textrm{容量}}{\textrm{价格}}\),即\(\dfrac{2^{i-1}}{c_i}\)。我们可以按照每个瓶子的性价比从高到低排序,依次选择......
  • 题解:CF913D Too Easy Problems
    题意给定一场考试,考试会持续\(T\)毫秒,由\(n\)道题目组成,你可以用\(t_i\)毫秒解决第\(i\)个问题,每个问题给定一个整数\(a_i\)。要求你选出一个试题集合\(S\),若该集合大小为\(k\),它应满足\(T\geq\sum_{i\inS}\limitst_i\),你需要最大化\(\sum_{i\inS}\limits[a_i......
  • 题解:P5618 [SDOI2015] 道路修建
    题意给定一个\(2\timesN\)的网格,网格上的点和上下左右连边。要求支持以下几种操作:修改某条边的边权。求满足\(y\in[l,r]\)的点构成的点集的最小生成树。分析这道题的想法和P4246[SHOI2008]堵塞的交通很相似。注意到\(N,M\leq6\times10^4\),并且查询的是......
  • 题解:P6089 [JSOI2015] 非诚勿扰
    分析首先我们要求出对于第\(i\)位女性,她选择每个列表中的男性的概率是多少。第一轮选择第一位的概率为\(p\),选择第二位的概率为\(p(1-p)\),以此类推。显然第一轮选择第\(k\)位的概率为\(p(1-p)^{k-1}\)。假设列表中有\(n\)名男性,那么第二轮选择第一位的概率为\(p(1-p......
  • 题解:P3968 [TJOI2014] 电源插排
    题意维护一个\(01\)串,初始均为\(0\),支持:单点将\(1\)修改为\(0\)。查询区间中\(1\)的个数。查询最长且最靠右的连续\(0\)段的靠右的中点,并将其改为\(1\)。分析第一个操作和第二个操作显然使用动态开点线段树维护。我们只需要解决第三个操作。我们用平衡树存储......