具有最优结构和重复子问题这两个要素的题适合使用动态规划。
如果该问题的最优解中包含了一个或多个最优子问题的解,这个问题具有最优子结构性质。
动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解。
求最长公共子序列(LCS)
一个给定序列的子序列是在该序列中删去若干元素后得到的序列。
给定两个序列X =<x1,x2,…xm>和Y=<y1,y2,…,yn>,找出X和Y的一个最长公共子序列。
这道题,同时也是牛客网的一道题。
例1:
X = <A B C BD A B>
Y = <B D C A B A>
输出为4
最长公共子序列为BCBA
例2:
X = <1 A 2 C 3 D 4 B 5 6>
Y = <B 1D 2 3 C A 4 5 B 6 A>
输出为6
最长公共子序列为123456
分析:
设X =<x1,x2,…,xm>和Y=<y1,y2,…,yn>的最长公共子序列为Z=<z1,z2,…,zk>
若 xm = yn , 则 zk= xm = yn ,且zk-1 是xm-1 和 yn-1 的最长公共子序列;
若 xm ≠ yn , 且 zk≠ xm,则zk是 xm-1 和 yn 的最长公共子序列;
若 xm ≠ yn , 且 zk≠ yn,则zk是xm 和 yn-1 的最长公共子序列;
用 c[i,j]来记录Xi和 Yj 的最长公共子序列的长度。
JAVA代码:
import java.util.*;
public class LCS {
public int findLCS(String A, int n, String B, int m) {
// write code here
int num =0;
int[][] c = new int[n+2][m+2];
for(int i1=0;i1<=n;i1++)
{Arrays.fill(c[i1],0);}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(A.charAt(i-1)==B.charAt(j-1))
{
c[i][j]=c[i-1][j-1]+1;
}
else
{
c[i][j] = c[i-1][j];
if(c[i][j-1]>c[i][j]) c[i][j] = c[i][j-1];
}
}
}
num = c[n][m];
return num;
}
}