题目链接

最长公共子序列

解题思路

第一思路:

1.用\(length[i][j]\)表示\(a\)串的前\(i\)个字符与\(b\)串的前\(j\)个字符重叠的最长子串长度

2.用\(num[i][j]\)表示 \(a\)串的前\(i\)个字符与\(b\)串的前\(j\)个字符重叠的最长子串个数

则求\(length[i][j],num[i][j]\)时有以下递推关系:

*\(length[i][j]:\)

如果当前两串结尾字符相等,则\(length[i][j]=length[i-1][j-1]+1\)

否则\(length[i][j]=max(length[i-1][j],length[i][j-1])\)

*\(num[i][j]:\)

如果\(length[i][j]\)与\(length[i-1][j]\)相等,\(num[i][j]\)可加\(num[i-1][j]\)

如果\(length[i][j]\)与\(length[i][j-1]\)相等,\(num[i][j]\)可加\(num[i][j-1]\)

如果\(length[i][j]\)与\(length[i-1][j-1]\)相等,则\(num[i][j]\)多加了个\(num[i-1][j-1]\),需要减去

代码:

#include<stdio.h>
#include<string.h>
#define max(a,b) (a>b?a:b)
int length[5010][5010],num[5010][5010],w=100000000;
char a[5010],b[5010];
int main(){
int i,j,la,lb;
scanf("%s%s",a,b);
la=strlen(a)-1;lb=strlen(b)-1;
for(i=0;i<=la;i++)num[i][0]=1;
for(i=0;i<=lb;i++)num[0][i]=1;
for(i=1;i<=la;i++){
for(j=1;j<=lb;j++){
if(a[i-1]==b[j-1]){
length[i][j]=length[i-1][j-1]+1;
num[i][j]=num[i-1][j-1];
}
else{
length[i][j]=max(length[i-1][j],length[i][j-1]);
if(length[i][j]==length[i-1][j-1])num[i][j]-=num[i-1][j-1];
num[i][j]+=w;
}
if(length[i-1][j]==length[i][j])num[i][j]+=num[i-1][j];
if(length[i][j-1]==length[i][j])num[i][j]+=num[i][j-1];
num[i][j]%=w;
length[i][j]%=w;
}
}
printf("%d\n%d",length[la][lb],num[la][lb]);
return 0;
}

提交效果

优化代码

考虑优化代码。

考虑到\(length\)、\(num\)数组当前状态都只与上一状态相关,可以用滚动数组优化空间和时间。

AC代码

#include<stdio.h>
#include<string.h>
#define max(a,b) (a>b?a:b)
int length[2][5010],num[2][5010],w=100000000;
char a[5010],b[5010];
int main(){
int i,j,la,lb;
scanf("%s%s",a,b);
la=strlen(a)-1;lb=strlen(b)-1;
for(i=0;i<=lb;i++)num[0][i]=1;
num[1][0]=1;
for(i=1;i<=la;i++){
int temp=i%2;
for(j=1;j<=lb;j++){
num[temp][j]=0;//滚动数组一定要注意这一点
if(a[i-1]==b[j-1]){
length[temp][j]=length[temp^1][j-1]+1;
num[temp][j]=num[temp^1][j-1];
}
else{
length[temp][j]=max(length[temp^1][j],length[temp][j-1]);
if(length[temp][j]==length[temp^1][j-1])num[temp][j]-=num[temp^1][j-1];
num[temp][j]+=w;
}
if(length[temp^1][j]==length[temp][j])num[temp][j]+=num[temp^1][j];
if(length[temp][j-1]==length[temp][j])num[temp][j]+=num[temp][j-1];
num[temp][j]%=w;
length[temp][j]%=w;
}
}
printf("%d\n%d",length[la%2][lb],num[la%2][lb]);
return 0;
}

提交效果

P2516 [HAOI2010]最长公共子序列 题解(LCS)的更多相关文章

  1. 洛谷P2516 [HAOI2010]最长公共子序列(LCS,最短路)

    洛谷题目传送门 一进来就看到一个多月前秒了此题的ysn和YCB%%% 最长公共子序列的\(O(n^2)\)的求解,Dalao们想必都很熟悉了吧!不过蒟蒻突然发现,用网格图貌似可以很轻松地理解这个东东? ...

  2. 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)

    2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...

  3. [HAOI2010]最长公共子序列(LCS+dp计数)

    字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X ...

  4. 洛谷 P2516 [HAOI2010]最长公共子序列

    题目传送门 解题思路: 第一问要求最长公共子序列,直接套模板就好了. 第二问要求数量,ans[i][j]表示第一个字符串前i个字符,第二个字符串前j个字符的最长公共子序列的数量 如果f[i][j]是由 ...

  5. luogu P2516 [HAOI2010]最长公共子序列

    传送门 首先那个\(O(n^2)\)的dp都会吧,不会自己找博客或者问别人,或是去做模板题(误) 对以下内容不理解的,强势推荐flash的博客 我们除了原来记录最长上升子序列的\(f_{i,j}\), ...

  6. 洛谷P2516 [HAOI2010]最长公共子序列

    题目描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y=& ...

  7. Luogu P2516 [HAOI2010]最长公共子序列 DP

    首先$LIS$显然:$f[i][j]=max(f[i][j-1],f[i-1][j],(a[i]==b[j])*f[i-1][j-1])$ 考虑如何转移数量: 首先,不管$a[i]$是否等于$b[j] ...

  8. P2516 [HAOI2010]最长公共子序列

    传送门 看到数据范围,显然 $n^2$ 的 $dp$... 设 $f[i][j]$ 表示 $A$ 串考虑了前 $i$ 位,$B$ 串考虑了前 $j$ 位,最优情况下的方案数 但是好像没法判断转移来的是 ...

  9. [BZOJ2423][HAOI2010]最长公共子序列

    [BZOJ2423][HAOI2010]最长公共子序列 试题描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x ...

随机推荐

  1. cmder设置方法

    一.添加鼠标右键 Cmder.exe /REGISTER ALL 二.添加系统环境变量 我的电脑 > 右键属性 > 高级系统设置 > 环境变量 > 系统变量,在path中添加 ...

  2. 833A The Meaningless Game

    A. The Meaningless Game time limit per test 1 second memory limit per test 256 megabytes input stand ...

  3. reCAPTCHA OCR 详解 , 验验证, OCR(光学自动识别)

    WEB安全专题 ‍‍reCAPTCHA的诞生及意义‍‍ CMU(卡耐基梅隆大学)设计了一个名叫reCAPTCHA的强大系统,让电脑去向人类求助.具体做法是:将OCR(光学自动识别)软件无法识别的文字扫 ...

  4. JavaScript string repeat methods All In One

    JavaScript string repeat methods All In One There are many ways in the ES-Next ways repeat ES2015 / ...

  5. CodeMirror动态修改代码(关键: editor.getDoc().setValue(data); editor.refresh();)

    在使用codemirror时,其原理是根据form中的textarea标签,自动加载其内容,获得代码行的显示.(具体使用方式参见 codemirror官网使用手册 http://codemirror. ...

  6. 26_ mysql数据操作语言:DELETE语句

    -- DELETE语句 -- 删除10部门中,工龄超过20年的员工记录 DELETE FROM t_emp WHERE deptno=10 AND DATEDIFF(NOW(),hiredate)/3 ...

  7. css中的transform,transition,translate的关系

    transform 旋转(transform是没有动画效果,你改变了它的值,元素的样子就唰的改变了.其中的位移的函数名就叫translate,所以说,translate是transform的一部分.) ...

  8. 能取值亦能赋值的Python切片

    切片,就像面包,给几刀,切成一片一片,可以做成吐司,也可以做成三明治,口味更佳: 列表(list).元组(tuple).字符串(str)都能进行切片,得到子片段,实际上切片操作比想象的要强大很多,能取 ...

  9. winform导出excel

    public void AllDataSetToExcel(DataSet ds) { string saveFileName = ""; bool fileSaved = fal ...

  10. ElasticSearch 搜索模板与建议

    公号:码农充电站pro 主页:https://codeshellme.github.io Search APIs 用于搜索和聚合存储在 ES 中的数据. 1,搜索模板 Template Search ...