您的位置:首页 > 其它

动态规划 最长公共子序列

2015-06-22 14:46 225 查看
动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算法将问题的解决方案视为一系列决策的结果,与贪婪算法不同的是,在贪婪算法中,每采用一次贪婪准则,便做出一个不可撤回的决策;而在动态规划算法中,还要考察每个最优决策序列中是否包含一个最优决策子序列,即问题是否具有最优子结构性质。

最长公共子序列:

最长公共自序列的问题也具有最优子结构的性质:X={x1,x2.......xm} Y={y1,y2,...yn},公共子序列为Z={z1,....zk}

1.若Xm=Yn,则xm=yn=zk,则Zk-1也是Xm-1,Yn-1的最长公共子序列

2,若Xm!=Yn,则xm!=zk,则Zk-1也是Xm-1,Yn的最长公共子序列

3.若Xm!=Yn,则yn!=zk,则Zk-1也是Xm,Yn-1的最长公共子序列

问题求解:

引进两个二维数组c[][]和b[][],c[][]表示最长公共自序列的长度,b[][]表示c[][]是怎么得到啦,以此搜索出最长的公共子序列字符串。

根据最优子结构,建立的递归关系公式为:

回溯输出的过程:

package com.liheng.algorithm;
/**
*
* @author Administrator
* 求公共子序列
* 功能:用动态规划的方法,求最长公共子序列
*/
public class MaxLen {
final static int maxLen=100;
public static void main(String[] args) {
// TODO Auto-generated method stub
//把数组都进行初始化
char []x = {'a','b','c','b','d','a','b','c'};
char []y = {'b','d','c','a','b','a','c'};
int m,n;
m = x.length;
n= y.length;
int  [][]c = new int[maxLen][maxLen];
int  [][]b = new int [maxLen][maxLen];
MaxLen ml = new MaxLen();
ml.LcslLength(m, n, x, y, c, b);
ml.printLCS(m,n,x,b);
}

void LcslLength(int m,int n,char x[],char y[],int c[][],int b[][])
{
int i,j;
//把第0行和第0列都赋值为0
for( i=0;i<=m;i++)
{
c[i][0] =0;
}
for( j=0;j<=n;j++)
{
c[0][i]=0;
}
//动态规划递归
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
//如果是两个相同的字符
if(x[i-1]==y[j-1])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}else if(c[i-1][j]>=c[i][j-1])
{ //表示两个字符不同
c[i][j] = c[i-1][j];
b[i][j] =2;
}else
{
c[i][j] = c[i][j-1];
}
}
}
}
void printLCS(int m,int n,char x[],int b[][])
{
//当字符创为0时,函数返回
if(m==0||n==0)
{
return;
}
//从后向前递归搜索
if(b[m]
==1)
{
printLCS(m-1,n-1,x,b);
System.out.print(x[m-1]+" ");
}
else if(b[m]
==2)
{
printLCS(m-1,n,x,b);
}
else
{
printLCS(m,n-1,x,b);
}
}

}


源代码:java
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: