DP解LCS问题模板及其优化

LCS--Longest Common Subsequence,即最长公共子序列,一般使用DP来解。

常规方法:

dp[i][j]表示字符串s1前i个字符组成的字符串与s2前j个字符组成的字符串的LCS的长度,则当s1[i-1]==s2[j-1]时,dp[i][j]=dp[i-1][j-1],否则dp[i][j]=max(dp[i-1][j],dp[i][j-1])。

最终的dp[len1][len2]即最终答案。代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 char s1[505],s2[505];
 7 int len1,len2;
 8 int dp[505][505];
 9
10 int main(){
11     while(~scanf("%s%s",s1,s2)){
12         len1=strlen(s1),len2=strlen(s2);
13         for(int i=0;i<=len1;++i) dp[i][0]=0;
14         for(int i=0;i<=len2;++i) dp[0][i]=0;
15         for(int i=1;i<=len1;++i)
16             for(int j=1;j<=len2;++j)
17                 if(s1[i-1]==s2[j-1])
18                     dp[i][j]=dp[i-1][j-1]+1;
19                 else
20                     dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
21         printf("%d\n",dp[len1][len2]);
22     }
23     return 0;
24 }

如果需要打印路径:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 char s1[505],s2[505];
 7 int len1,len2;
 8 int dp[505][505],path[505][505];
 9
10 void print(int p1,int p2){
11     if(p1==0||p2==0) return;
12     else{
13         if(path[p1][p2]==1) print(p1-1,p2-1),printf("%c",s1[p1-1]);
14         else if(path[p1][p2]==2) print(p1-1,p2);
15         else print(p1,p2-1);
16     }
17 }
18
19 int main(){
20     while(~scanf("%s%s",s1,s2)){
21         len1=strlen(s1),len2=strlen(s2);
22         for(int i=0;i<=len1;++i) dp[i][0]=0;
23         for(int i=0;i<=len2;++i) dp[0][i]=0;
24         for(int i=1;i<=len1;++i)
25             for(int j=1;j<=len2;++j)
26                 if(s1[i-1]==s2[j-1])
27                     dp[i][j]=dp[i-1][j-1]+1,path[i][j]=1;
28                 else if(dp[i-1][j]>=dp[i][j-1])
29                     dp[i][j]=dp[i-1][j],path[i][j]=2;
30                 else
31                     dp[i][j]=dp[i][j-1],path[i][j]=3;
32         printf("%d\n",dp[len1][len2]);
33         print(len1,len2);
34         printf("\n");
35     }
36     return 0;
37 }

空间优化:

实际上只需要dp[n]就行了,滚动数组。因为dp[i][j]由dp[i-1][j-1],dp[i-1][j],dp[i][j-1],用dp[j]表示dp[i][j],则更新dp[j]时用pre存储dp[i-1][j-1],此时的dp[j-1]表示dp[i][j-1],此时的dp[j]表示dp[i-1][j],这样就大大优化了空间,详见代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 char s1[505],s2[505];
 7 int len1,len2,pre,tmp;
 8 int dp[505];
 9
10 int main(){
11     while(~scanf("%s%s",s1,s2)){
12         len1=strlen(s1),len2=strlen(s2);
13         memset(dp,0,sizeof(dp));
14         for(int i=1;i<=len1;++i){
15             pre=0;
16             for(int j=1;j<=len2;++j){
17                 tmp=dp[j];
18                 if(s1[i-1]==s2[j-1])
19                     dp[j]=pre+1;
20                 else
21                     dp[j]=max(dp[j-1],dp[j]);
22                 pre=tmp;
23             }
24         }
25         printf("%d\n",dp[len2]);
26     }
27     return 0;
28 }

时间优化:

据说可以将LCS转换为LIS解法,从而使时间复杂度降为O(nlogn),但似乎在某些特殊情况复杂度比常规做法更麻烦,不被建议使用。等以后接触时再更......

原文地址:https://www.cnblogs.com/FrankChen831X/p/10423287.html

时间: 2024-11-05 22:07:50

DP解LCS问题模板及其优化的相关文章

Bitmap详解与Bitmap的内存优化

感觉这里的排版看着更舒服些 Bitmap详解与Bitmap的内存优化 一.Bitmap: Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件. 常用方法: + public void recycle() // 回收位图占用的内存空间,把位图标记为Dead + public final boolean isRecycled() //判断位图内存是否已释放 + public final int getWid

dp解Codeforces Round #260 (Div. 2)C. Boredom

#include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector> #include<algorithm> using namespace std; lo

插头dp的几个模板

/* ural1519 求经过全部可行点的哈密顿回路的个数 括号匹配法,转移有点复杂,可是时间空间比較小 */ #include<cstdio> #include<cstring> #include<string> #include<iostream> #include<algorithm> #include<cmath> #include<map> #include<queue> #define LL lon

虚拟机之模板机优化与克隆

虚拟机之模板机优化 模板机优化之hosts配置文件优化 \cp /etc/hosts{,.bak} cat >/etc/hosts<<EOF 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.16.1.5 lb01 172.16.1.6

Myeclipse Templates详解(一) —— Java模板基础

目录 Templates简介 MyEclipse自带Templates详解 新建Template 自定义Template 因为自己比较懒,尤其是对敲重复代码比较厌恶,所以经常喜欢用快捷键和模板,Myeclipse的模板功能其实很强大,好像自己只用过syso这一个,所以最近学习了一下,初次写博客,谢绝转载. 一.Templates简介 1.1 Templates基本介绍 Myeclipse模板的查看编辑入口,Window->Preferences->Java->Editor->Tem

LIS,LCS,LICS模板

最长递增子序列模板(1) #include<iostream> #include<algorithm> #include<cstdio> using namespace std; int main() { int n; int ans = 0; int dp[1005]; int num[1005]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&num[

解数独算法的实现——剪枝优化

最近人工智能做个小实验,组队选了个数独游戏,顺便研究了一下.解数独感觉主流思想也就是深搜回溯了吧,优化就是各种剪枝方法. 1 引言 数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵(Latin Square),曾风靡日本和英国.现有解法包括基础解法:摒除法,余数法,进阶解法:区块摒除法(Locked Candidates).数组法(Subset).四角对角线(X-Wing).唯一矩形(Unique Rectangle).全双值坟墓(Bivalue Universal Grave).单数链(X

ZOJ 3632 Watermelon Full of Water(dp+线段树或单调队列优化)

Watermelon Full of Water Time Limit: 3 Seconds      Memory Limit: 65536 KB Watermelon is very popular in the hot summer. Students in ZJU-ICPC Team also love watermelon very much and they hope that they can have watermelon to eat every day during the

poj3744--Scout YYF I(概率dp第五弹:矩阵优化)

Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5093   Accepted: 1385 Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties,