线性DP(中)
线性DP(中)
1.经典例题(3):最长公共子序列
一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列
给定两个序列
题目描述
给定两个序列
输入
共有两行。每行为一个由大写字母构成的字符串,表示序列
输出
第一行为一个非负整数。表示所求得的最长公共子序列的长度。若不存在公共子序列.则输出文件仅有一行输出一个整数0。
输入样例
ABCBDAB BDCABA
输出样例
4
数据范围
提示
最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:
子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;
也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。字符串长度小于等于1000。
注:本题来源于信息学奥赛一本通第1265题
2.经典例题(3)思路
题目让我们求最长公共子序列,
那我们不妨把
状态转移则可以把每一集合分成四个子集:
两个序列中都不含最后一个字母的;
只含第一个序列中最后一个字母的;
只含第二个序列中最后一个字母的;
两个序列中都含最后一个字母的。
第一种和第四种的表示好推,
第一种:
第四种:直接算不好算,那就先都不含最后一个字母,最后长度加1
有人就说了:“这第二种和第三种不是很好推吗?不就是
但真的是这样吗?
有没有发现,这两个序列是没有以同一个字母结尾的,也就是说它们跟我们要求的就不是一个东西。
但即使不以同一个字母结尾又怎样,有重叠又怎样?
用就完了!!!
注1:第一种情况可以被第二种情况和第三种情况替代,所以不用写出来。
注2:第四种情况不一定会出现,所以得加上一个特判。
3.经典例题(3)代码(注释已全部标出)
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int N=1005; int la,lb; char a[N],b[N]; int f[N][N]; int main(){ scanf("%s%s",a+1,b+1);//用cin好像不太行,这个题得从下标为1的地方开始输入 int la=strlen(a+1),lb=strlen(b+1);//求长度 for(int i=1;i<=la;i++) for(int j=1;j<=lb;j++){ f[i][j]=max(f[i-1][j],f[i][j-1]);//状态转移方程 if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);//特判 } printf("%d",f[la][lb]); return 0; }
完awa~
如果觉得还行就点个赞吧,您的支持是本蒟蒻最大的动力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】