动态规划法求解最长公共子序列(含Java代码)

动态规划法求解最长公共子序列(含Java代码)
动态规划法求解最长公共子序列(含Java代码)

公共子序列问题徐康123183

一.算法设计

假设有两个序列X和Y,假设X和Y分别有m和n个元素,则建立一个二维数组C[(m+1)*(n+1)],记录X i与Y j的LCS的长度。将C[i,j]分为三种情况:

若i =0 或j =0时,C[i,j]=0;

若i,j>0且X[i]=Y[j],C[i,j]=C[i-1,j-1]+1;

若i,j>0且X[i] Y[j],C[i,j]=max{C[i-1,j],C[i,j-1]}。

再使用一个m*n的二维数组b,b[i,j]记录C[i,j]的来向:

若X[i]=Y[j],则B[i,j]中记入“↖”,记此时b[i,j] = 1;

若X[i] Y[j]且C[i-1,j] > C[i,j-1],则b[i,j]中记入“↑”,记此时B[i,j] = 2;

若X[i] Y[j]且C[i-1,j] < C[i,j-1],则b[i,j]中记入“←”,记此时B[i,j] = 3;

若X[i]Y[j]且C[i-1,j] = C[i,j-1],则b[i,j]中记入“↑”或“←”,记此时B[i,j] = 4;

得到了两个数组C[]和B[],设计递归输出LCS(X,Y)的算法:

LCS_Output(Direction[][], X[], i, j, len,LCS[]){

If i=0 or j=0 将LCS[]保存至集合LCS_SET中

then return;

If b[i,j]=1 then /*X[i]=Y[j]*/

{LCS_Output(b,X,i-1,j-1);

将X[i]保存至LCS[len-i];}

else if b[i,j]=2 then /*X[i]≠Y[j]且C[i-1,j]>C[i,j-1]*/

LCS_Output(b,X,i-1,j)

else if b[i,j]=3 then /*X[i]≠Y[j]且C[i-1,j]

else if b[i,j]=4 then /*X[i]≠Y[j]且C[i-1,j]=C[i,j-1]*/

LCS_Output(b,X,i-1,j)

LCS_Output(b,X,i,j-1)

}

二.算法时间复杂度分析

由上述对算法的分析得知,求辅助数组C 和B 所消耗的时间复杂度为O (mn ),而查找所有的公共子序列的时间复杂度取决于所遍历的路径,而路径是由算法递归的方向决定的。显然,最好的情况是m=n 并且B 中的所有值都为1(按斜对角线方向搜索),此时时间复杂度为O (n )。当X 和Y 序列不存在公共子序列时为算法的最坏情况,因为此时C 数组的所有元素都为0,B 在每一个节点都要沿着两个不同的方向搜索,即每次都要调用两次LCS_Output,当调用到i=0或j=0时返回,直到搜索完整个m*n 数组才结束。

该时间复杂度就是计算从点(m,n )到i=0或j=0的所有路径。建立如上图的直角坐标系,设点S (m ,n ),x 轴上的坐标点P 1(1,0) 到Pm(m,0),y 轴上的系列坐标点Q 1(0,1) 到Qn(0,n)。

因为j i Q P 和是搜索路径的边界上的点,点1+i P 不能直接到达点i P ,点1+j Q 也不能直接到达j Q ,所以点),(n m S 到m i P P P P ,...,,...,,21和n j Q Q Q Q ,...,,...,,21的路径数等价于),(n m S 到点

)1,('),...,1,('),...,1,2('),1,1('21m P i P P P m i 和点),1('),...,,1('),...,2,1('),1,1('21n Q j Q Q Q n j 的路径数,又因为

点),(n m 到),(j i 路径数为i

n j i n m C ---+,设总路径数为t ,则有

()()

m m

n n m n n m n n m n m m n n m n n n m m n m m n m m n m n n m n m

j j

m j

m n n

i i

n i

n m C C C C C C C C C C C C C C C C

t ++-+--+--+--+---+--+---+--+=--+-=--+-===+=+=+++++++++=+=∑∑11111110

11231201123121

11

1...... 三.程序流程图如下所示

四.程序源码

package Homework2;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.HashSet;

import java.util.Set;

public class LCS {

int C[][];

int B[][];

Set LCS_SET = new HashSet(); //使用集合去重

public int LCSLength(char X[], char Y[]) { //返回公共子序列长度int m = X.length;

int n = Y.length;

C = new int[X.length][Y.length];

B = new int[X.length][Y.length];

for (int i = 0; i < m; i++) {

C[i][0] = 0;

B[i][0] = 0;

}

for (int j = 0; j < n; j++) {

C[0][j] = 0;

B[0][j] = 0;

}

for (int i = 1; i < m; i++) {

for (int j = 1; j < n; j++) {

if (X[i] == Y[j]) {

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 if (C[i - 1][j] < C[i][j - 1]) {

C[i][j] = C[i][j - 1];

B[i][j] = 3;

} else {

C[i][j] = C[i - 1][j];

B[i][j] = 4;

}

}

}

return C[m - 1][n - 1];

}

public void LCS_Output(int Direction[][], char X[], int i, int j, int len, char LCS[]) {

int lcslen = len;

if (i == 0 || j == 0) {

LCS_SET.add(String.valueOf(LCS));

return;

}

if (B[i][j] == 1) {

LCS[len - 1] = X[i];

len--;

LCS_Output(B, X, i - 1, j - 1, len, LCS);

} else if (B[i][j] == 2) {

LCS_Output(B, X, i - 1, j, len, LCS);

} else if (B[i][j] == 3) {

LCS_Output(B, X, i, j - 1, len, LCS);

} else if (B[i][j] == 4) {

LCS_Output(B, X, i - 1, j, len, LCS);

LCS_Output(B, X, i, j - 1, len, LCS);

}

}

/**

*@param args

*/

public static void main(String[] args) throws IOException { // TODO Auto-generated method stub

char X[], Y[];

BufferedReader buf = null;

buf = new BufferedReader(new InputStreamReader(System.in));

System.out.println("请输入一个序列");

X = buf.readLine().toCharArray();

char X_temp[] = new char[X.length + 1];

for (int i = 0; i < X.length; i++) {

X_temp[0] = ' ';

X_temp[i + 1] = X[i];

}

System.out.println("请输入一个序列");

Y = buf.readLine().toCharArray();

char Y_temp[] = new char[Y.length + 1];

for (int i = 0; i < Y.length; i++) {

Y_temp[0] = ' ';

Y_temp[i + 1] = Y[i];

}

System.out.print("X=");

for (char x : X) {

System.out.print(x);

}

System.out.println();

System.out.print("Y=");

for (char y : Y) {

System.out.print(y);

}

System.out.println();

LCS lcs = new LCS();

int len = lcs.LCSLength(X_temp, Y_temp);

char LCS[] = new char[len];

int m = X.length;

int n = Y.length;

System.out.println("最长公共子序列长度为:" + len); // 输出最长子序列长度System.out.print("最长公共子序列有:");

lcs.LCS_Output(lcs.B, X_temp, m, n, len, LCS);

System.out.print(lcs.LCS_SET); // 输出子序列集合中的元素}

}

五.运行结果截图

1.输入abc和acb

2.输入asd和xcv

3.输入ABCBDAB 和BDCABA

经检查输出结果均正确!

最长公共子序列问题(最)

算法作业: LCS 问 题 作业要求:设计一个算法求出两个序列的所有LCS ,分析最坏情况,用“会计方法”证明利用b[i][j]求出 所有LCS 的算法在最坏情况下时间复杂度为)(m m n C O + 1、 算法思路: 根据最长公共子序列问题的性质,即经过分解后的子问题具有高度重复性,并且具有最优子结构性质,采用动态规划法求解问题。设X={x 1, x 2, … , x n }, Y={y 1, y 2, … , y m }, 首先引入二维数组C[i][j]记录X i 和Y j 的LCS 的长度,定义C[i][j]如下: { j i j y i 且x ,i,j ]][j C[i j y i x j i j i C j i C j i C 00001110,]},1][[],][1[max{]][[===>+--≠>--=或,且 为了构造出LCS ,还需要使用一个二维数组b[m][n],b[i][j]记录C[i][j]是通过哪个子问题的值求得 的,以决定搜索的方向,欲求出所有的LCS ,定义数组b 如下: 设1-对角线方向;2-向上;3-向左;4-向上或向左 若X[i]=Y[j],b[i][j] = 1, 若C[i-1][j][i][j-1], 则b[i][j] = 3, 若C[i-1][j]=[i][j-1], 则b[i][j] = 4, 根据以上辅助数组C 和b 的定义,算法首先需要求出这两个数组, C[m][n]中记录的最长公共子序列的长度,b 中记录了查找子序列元素的搜索方向。 利用C 和b 的信息,Find_All_LCS 可以采用回溯法求出所有的LCS 。基本思路如下:使用一个辅助数组记录每次调用Find_All_LCS 得到的LCS 中的元素,每次递归调用一次Find_All_LCS ,进入一个新的执行层,首先要判断当前处理的两个子序列长度是否大于等于0 ,若不满足,则该层的递归结束,返回上一层;然后再判断当前得到的子序列是否等于数组C 中求出的最长公共子序列长度,若等于,则说明算法执行到此已经得到一个LCS ,按序输出;若不等于,此时根据数组b 中记录的搜索方向继续搜索,特别要说明的是,当b[i][j]=4时,即要向上或向左,需要对这两个方向分别调用Find_All_LCS ,保证沿着这两个方向上LCS 元素不被漏掉,都可以搜索到;若b[i][j]=1,即沿对角线方向搜索前进时,此时元素X[i]为LCS 中的元素,存放至辅助数组中去,同时将当前已经求得的LCS 长度增1,当递归调用Find_All_LCS 从b[i][j]=1处时,需要回溯一步,搜索其它路径上可能为LCS 中的元素。当所有的可能路径都已经搜索完,算法结束。 对于某些情况会输出重复的LCS ,这是因为算法在沿不同路径搜索时可能会出现相同的LCS 序列。 2、 时间复杂度分析 由上述对Find_All_LCS 算法的分析可知,求出所有的LCS 实际上是根据搜索的方向信息遍历所有的路径找出满足条件的元素集合。因此,除求解辅助数组C 和b 所用的O(mn+m+n)的执行时间外,Find_All_LCS 的时间复杂度取决于所遍历路径数。而路径数是由搜索方向决定的。显然算法在最好的情况下,即m=n 并且b 中所有的值都指示沿着对角线方向搜索,时间复杂度为O(n). 相反,当X 和Y 序列不存在公共子序列时为算法的最坏情况,此时C 中所有值都等于0,数组b 中所有的值都指示要分别沿两个不同的方向(向左或向上)搜索,这种情况下每处理一次X[i],Y[j]时总是要沿两个方向分别调用Find_All_LCS ,遇到i=0或j=0时返回,直到搜索完所有的可能路径才结束,最坏情况下的搜索矩阵如下图所示:

(数学建模教材)4第四章动态规划

第四章动态规划 §1 引言 1.1 动态规划的发展及研究内容 动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20 世纪50 年代初R. E. Bellman 等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优性原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,逐个求解,创立了解决这类过程优化问题的新方法—动态规划。1957 年出版了他的名著《Dynamic Programming》,这是该领域的第一本著作。 动态规划问世以来,在经济管理、生产调度、工程技术和最优控制等方面得到了广泛的应用。例如最短路线、库存管理、资源分配、设备更新、排序、装载等问题,用动态规划方法比用其它方法求解更为方便。 虽然动态规划主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。 应指出,动态规划是求解某类问题的一种方法,是考察问题的一种途径,而不是一种特殊算法(如线性规划是一种算法)。因而,它不象线性规划那样有一个标准的数学表达式和明确定义的一组规则,而必须对具体问题进行具体分析处理。因此,在学习时,除了要对基本概念和方法正确理解外,应以丰富的想象力去建立模型,用创造性的技巧去求解。 例1 最短路线问题 图1 是一个线路网,连线上的数字表示两点之间的距离(或费用)。试寻求一条由A 到G距离最短(或费用最省)的路线。 图1 最短路线问题 例2 生产计划问题 工厂生产某种产品,每单位(千件)的成本为1(千元),每次开工的固定成本为3 (千元),工厂每季度的最大生产能力为6(千件)。经调查,市场对该产品的需求量第一、二、三、四季度分别为2,3,2,4(千件)。如果工厂在第一、二季度将全年的需求都生产出来,自然可以降低成本(少付固定成本费),但是对于第三、四季度才能上市的产品需付存储费,每季每千件的存储费为0.5(千元)。还规定年初和年末这种产品均无库存。试制定一个生产计划,即安排每个季度的产量,使一年的总费用(生产成本和存储费)最少。 1.2 决策过程的分类根据过程的时间变量是离散的还是连续的,分为离散时间 决策过程(discrete-time -56-

求最长子序列的长度

一,最长递增子序列问题的描述 设L=是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=,其中k1是对序列L=按递增排好序的序列。那么显然X与L的最长公共子序列即为L的最长递增子序列。这样就把求最长递增子序列的问题转化为求最长公共子序列问题LCS了。 最长公共子序列问题用动态规划的算法可解。设Li=< a1,a2,…,a i>,Xj=< b1,b2,…,b j>,它们分别为L和X的子序列。令C[i,j]为Li与Xj的最长公共子序列的长度。则有如下的递推方程: 这可以用时间复杂度为O(n2)的算法求解,由于这个算法上课时讲过,所以具体代码在此略去。求最长递增子序列的算法时间复杂度由排序所用的O(nlogn)的时间加上求LCS的O(n2)的时间,算法的最坏时间复杂度为O(nlogn)+O(n2)=O(n2)。 三,第二种算法:动态规划法 设f(i)表示L中以a i为末元素的最长递增子序列的长度。则有如下的递推方程: 这个递推方程的意思是,在求以a i为末元素的最长递增子序列时,找到所有序号在L前面且小于a i的元素a j,即j

动态规划算法原理与的应用

动态规划算法原理及其应用研究 系别:x x x 姓名:x x x 指导教员: x x x 2012年5月20日

摘要:动态规划是解决最优化问题的基本方法,本文介绍了动态规划的基本思想和基本步骤,并通过几个实例的分析,研究了利用动态规划设计算法的具体途径。关键词:动态规划多阶段决策 1.引言 规划问题的最终目的就是确定各决策变量的取值,以使目标函数达到极大或极小。在线性规划和非线性规划中,决策变量都是以集合的形式被一次性处理的;然而,有时我们也会面对决策变量需分期、分批处理的多阶段决策问题。所谓多阶段决策问题是指这样一类活动过程:它可以分解为若干个互相联系的阶段,在每一阶段分别对应着一组可供选取的决策集合;即构成过程的每个阶段都需要进行一次决策的决策问题。将各个阶段的决策综合起来构成一个决策序列,称为一个策略。显然,由于各个阶段选取的决策不同,对应整个过程可以有一系列不同的策略。当过程采取某个具体策略时,相应可以得到一个确定的效果,采取不同的策略,就会得到不同的效果。多阶段的决策问题,就是要在所有可能采取的策略中选取一个最优的策略,以便得到最佳的效果。动态规划是一种求解多阶段决策问题的系统技术,可以说它横跨整个规划领域(线性规划和非线性规划)。在多阶段决策问题中,有些问题对阶段的划分具有明显的时序性,动态规划的“动态”二字也由此而得名。动态规划的主要创始人是美国数学家贝尔曼(Bellman)。20世纪40年代末50年代初,当时在兰德公司(Rand Corporation)从事研究工作的贝尔曼首先提出了动态规划的概念。1957年贝尔曼发表了数篇研究论文,并出版了他的第一部著作《动态规划》。该著作成为了当时唯一的进一步研究和应用动态规划的理论源泉。在贝尔曼及其助手们致力于发展和推广这一技术的同时,其他一些学者也对动态规划的发展做出了重大的贡献,其中最值得一提的是爱尔思(Aris)和梅特顿(Mitten)。爱尔思先后于1961年和1964年出版了两部关于动态规划的著作,并于1964年同尼母霍思尔(Nemhauser)、威尔德(Wild)一道创建了处理分枝、循环性多阶段决策系统的一般性理论。梅特顿提出了许多对动态规划后来发展有着重要意义的基础性观点,并且对明晰动态规划路径的数

(完整word版)最长公共子序列长度算法

// KSY.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include using namespace std; void LCSLength(int m,int n,char *x ,char *y, int **c, int **b) { int i ,j; for (i = 1; i <= m; i++) c[i][0] = 0; for (i = 1; i <= n; i++) c[0][i] = 0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) {

if (x[i]==y[j]) { 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]; b[i][j]=3; } } } void LCS(int i ,int j, char *x ,int **b) { if (i ==0 || j==0) return; if (b[i][j]== 1) { LCS(i-1,j-1,x,b); printf("%c",x[i]); } else if (b[i][j]== 2) LCS(i-1,j,x,b); else LCS(i,j-1,x,b); } const int M = 6; const int N = 5; void output(char *s,int n); void LCSLength(int m,int n,char *x,char *y,int * *c,int * *b); void LCS(int i,int j,char *x,int * *b); void main() { char x[] = {' ','B','C','E','F','G','T'}; char y[] = {' ','C','D','F','J','G'}; int **c = new int *[M+1]; int **b = new int *[M+1]; for(int i=0;i<=M;i++) { c[i] = new int[N+1]; b[i] = new int[N+1]; } cout<<"序列X:"<

第四章 数学规划模型

第四章 数学规划模型 【教学目的】:深刻理解线性规划,非线性规划,动态规划方法建模的基本特点,并能熟练建立一些实际问题的数学规划模型;熟练掌握用数学软件(Matlab ,Lindo ,Lingo 等)求解优化问题的方法。 【教学重点难点】: 教学重点:线性规划和非线性规划的基本概念和算法,解决数学规划问题的一般思路和 方法,线性规划模型、整数规划模型、非线性规划模型的构建及其Matlab 与Lingo 实现。 教学难点:区分线性规划模型和非线性模型适用的实际问题,以及何时采用线性模型, 何时采用非线性模型,线性模型与非线性模型的转化。 【课时安排】:10学时 【教学方法】:采用多媒体教学手段,配合实例教学法,通过对典型例题的讲解启发学生思维,并给与学生适当的课后思考讨论的时间,加深知识掌握的程度。安排一定课时的上机操作。 【教学内容】: 在众多实际问题中,常常要求决策(确定)一些可控制量的值,使得相关的量(目标)达到最佳(最大或最小)。这些问题就叫优化问题,通常需要建立规划模型进行求解。称这些可控制量为决策变量,相关的目标量为目标函数;一般情况下,决策变量x 的取值是受限制的,不妨记为x ∈Ω,Ω称为可行域,优化问题的数学模型可表示为 Max(或Min)f(x), x ∈Ω 一般情况下,x 是一个多元变量,f(x)为多元函数,可行域比较复杂,一般可用一组不等式组来表示,这样规划问题的一般形式为 () x Min f x . ()0,1,2,,i st g x i m ≤= 虽然,该问题属于多元函数极值问题,但变量个数和约束条件比较多,一般不能用微分法进行解决,而通过规划方法来求解;这里讨论的不是规划问题的具体算法,主要是讨论如何将一个实际问题建立优化模型,并利用优化软件包进行求解。 根据目标函数和约束函数是否为线性,将规划模型分为线性规划和非线性规划。 4.1线性规划 线性规划(LP)研究的实际问题多种多样的,它在工农业生产、经济管理、优化设计与控

第13讲 第四章《城乡规划法》配套行政法规与规章(五)及第五章城市规划技术标准与规范(一)(2011年新版)

8、《近期建设规划工作暂行办法》 2002年建设部制定了《近期建设规划工作暂行办法》和《城市规划强制性内容暂行规定》(建规[2002]218号),要求各地依据《办法》和《规定》,切实抓紧组织制定近期建设规划和明确城市规划强制性内容工作。 (1)近期建设规划的基本任务(第四条) (2)编制近期建设规划遵循原则(第五、六条) (3)近期建设规划的强制性内容(第七条) (4)近期建设规划的指导性内容(第八、九条) (5)近期建设规划的审批(第十条) 9、《城市规划强制性内容暂行规定》 (1)城市规划强制性内容的定义(第二条) (2)城市规划强制性内容的基本要求(第三、四条) (3)省域城镇体系规划的强制性内容(第五条) (4)城市总体规划的强制性内容(第六条) (5)城市详细规划的强制性内容(第七条) (6)有关规划强制性内容的调整(第九至十一条) 10、《城市紫线管理办法》 建设部制定的《城市紫线管理办法》,2003年11月15日建设部第22次常务会议审议通过,自2004年2月1日起施行。 (1)城市紫线定义 本办法所称城市紫线,是指国家历史文化名城内的历史文化街区和省、自治区、直辖市人民政府公布的历史文化街区的保护范围界线,以及历史文化街区外经县级以上人民政府公布保护的历史建筑的保护范围界线。本办法所称紫线管理是划定城市紫线和对城市紫线范围内的建设活动实施监督、管理。 (2)主管部门(第四条) (3)划定紫线应当遵循的原则(第六条) (4)城市紫线的调整与撤销(第八、十一条)。 (5)城市紫线范围内禁止进行下列活动(第十三条)。 (6)紫线范围内建设的要求(第十二、十四至十七条)。 11、《城市绿线管理办法》 建设部制定的《城市绿线管理办法》,2002年9月9日建设部第63次常务会议审议通过,随后发布,

经典算法——动态规划教程

动态规划是对最优化问题的一种新的算法设计方法。由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的没计法对不同的问题,有各具特色的表示方式。不存在一种万能的动态规划算法。但是可以通过对若干有代表性的问题的动态规划算法进行讨论,学会这一设计方法。 多阶段决策过程最优化问题 ——动态规划的基本模型 在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。因此各个阶段决策的选取不能任意确定,它依赖于当前面临的状态,又影响以后的发展。当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线。这种把一个问题看做是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问题称为多阶段决策最优化问题。 【例题1】最短路径问题。图中给出了一个地图,地图中每个顶点代表一个城市,两个城市间的连线代表道路,连线上的数值代表道路的长度。现在,想从城市A到达城市E,怎样走路程最短,最短路程的长度是多少? 【分析】把从A到E的全过程分成四个阶段,用k表示阶段变量,第1阶段有一个初始状态A,两条可供选择的支路ABl、AB2;第2阶段有两个初始状态B1、 B2,B1有三条可供选择的支路,B2有两条可供选择的支路……。用dk(x k,x k+1)表示在第k阶段由初始状态x k到下阶段的初始状态x k+1的路径距离,Fk(x k)表示从第k阶段的x k到终点E的最短距离,利用倒推方法求解A到E的最短距离。具体计算过程如下: S1:K=4,有:F4(D1)=3,F4(D2)=4,F4(D3)=3 S2: K=3,有: F3(C1)=min{d3(C1,D1)+F4(D1),d3(C1,D2)+F4(d2)}=min{8,10}=8 F3(C2)=d3(C2,D1)+f4(D1)=5+3=8 F3(C3)=d3(C3,D3)+f4(D3)=8+3=11 F3(C4)=d3(C4,D3)+f4(D3)=3+3=6

最长公共子序列实验报告

河北地质大学课程设计报告 (学院)系: 信息工程学院 专业: 计算机科学与技术 姓名: 李义 班级: 二班 学号: 515109030227 指导教师: 王培崇 2016年11月26 日

算法课程设计报告 姓名李义学号515109030227 日期2016/11/10-2016/12/1 实验室152 指导教师王培崇设备编号08 设计题目求最长公共子序列 一、设计内容 求最长公共子序列,如输入字符串str1=adadsda,str2=sadasfda。 则求出的最长公共子序列是adasda。 二、设计目的 掌握动态规划思想,对使用求最长公共子序列加深理解。 三、设计过程 1.算法设计 1. for i ←0 to n 2. L[i,0] ←0 3. end for 4. for j ←0 to m 5. L[0,j] ←0 6. end for 7. for i ←1 to n 8. for j ←1 to m 9. if ai=bj then L[i,j]←L[i-1,j-1]+1 10. else L[i,j]←max {L[i,j-1], L[i-1,j] } 11. end if 12. end for 13. end for 14. return L[n,m] 2.流程图

开始结束 输入I=0,j=0 i<=n L[I,0]=0 i++ Y L[0,j]=0 N j<=n j++ Y i=1 to n J=1 to m ai=bj L[i,j]=L[i-1,j-1]+1 L[i,j]=max{L[i-1,j ],L[i,j-1]} Y J++i++ N 图1.Lcs 算法 3.数据结构 str1=adadsda str2=sadasfda 四、程序实现及运行结果

动态规划解最长公共子序列问题

动态规划解最长公共子序列问题 动态规划主要针对最优化问题,它的决策是全面考虑不同的情况分别进行决策,,最后通过多阶段决策逐步找出问题的最终解.当各个阶段采取决策后,会不断决策出新的数据,直到找到最优解.每次决策依赖于当前状态,又随机引起状态的转移.一个决策序列就是在变化的状态中产生出来的,故有”动态”的含义.所以,这种多阶段最优化决策解决问题的过程称为动态规划. 一问题的描述与分析 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干字符(可能一个也不去掉)后形成的字符序列..令给定的字符序列X=”x0,x1,x2,…xm-1”,序列Y=”y0,y1,…yk-1”是X的子序列,存在X的一个严格递增下标序列i=i0,i1,i2,…ik-1,使得对所有的j=0,1,2,…k-1,有xi=yi。例如X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。 给定两个序列A和B,称序列Z是A和B公共子序列,是指Z同是A和B的子序列。求最长公共子序列。 若A的长度为m,B的长度为n,则A的子序列有2*m-1个,B的子序列有2*n-1个。采用枚举法分别对A和B的所以子序列一一检查,最终求出最长公共子序列。如此比较次数(2*2n)接近指数阶,当n较大时,算法太耗时,不可取。所以要全面考虑不同的情况分别进行决策,,最后通过多阶段决策逐步找出问题的最终解.当各个阶段采取决策后,会不断决策出新的数据,直到找到最优解。 二、算法设计(或算法步骤) A=”a0,a1,a2,……am-1”,B=”b0,b1,b2,……bn-1”,且Z=”z0,z1,z2……zk-1”,为她们的最长公共子序列。不难证明有一下结论: (1)如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,z2,……zk-2”是“a0,a1,a2,…… am-2”和“b0,b1,b2,……bn-2”的一个最长公共子序列; (2)如果am-1!=bn-1,则若zk-1!=am-1,则“z0,z1,z2,……zk-1”是“a0,a1,a2,…… am-2”和”b0,b1,b2,……bn-1”的一个最长公共子序列。 (3)如果am-1!=bn-1,则若zk-1!=bn-1,则“z0,z1,z2,……zk-1”是“a0,a1,a2,…… am-1”和“b0,b1,b2,……bn-2”的一个最长公共子序列。 如此找到了原问题与其子问题的递归关系。 基本存储结构是存储两个字符串及其最长公共子序列的3个一位数组。当然要找出最长公共子序列,要存储当前最长公共子序列的长度和当前公共子序列的长度,而若只存储当前信息,最后只能求解最长公共子序列的长度,却不能找到最长公共子序列本身。因此需建立一个(n+1)*(m+1)的二维数组c,c[i][j]存储序列“a0,a1,a2……ai-2”和“b0,b1,……bj-1”的最长公共子序列长度,由上递推关系分析,计算c[i][j]可递归的表述如下: (1)c[i][j]=0 如果i=0或j=0;

最长公共子序列问题

2.3最长公共子序列问题 和前面讲的有所区别,这个问题的不涉及走向。很经典的动态规划问题。 例题16 最长公共子序列 (lcs.pas/c/cpp) 【问题描述】 一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X= < x1, x2,…, xm>,则另一序列Z= < z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列< i1, i2,…, ik>,使得对于所有j=1,2,…,k有Xij=Zj 例如,序列Z=是序列X=的子序列,相应的递增下标序列为<2,3,5,7>。给定两个序列X 和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X= < A, B, C, B, D, A, B>和Y= < B, D, C, A, B, A>,则序列是X和Y的一个公共子序列,序列也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。 给定两个序列X= < x1, x2, …, xm>和Y= < y1, y2, … , yn>,要求找出X和Y的一个最长公共子序列。 【输入文件】 输入文件共有两行,每行为一个由大写字母构成的长度不超过200的字符串,表示序列X和Y。 【输出文件】 输出文件第一行为一个非负整数,表示所求得的最长公共子序列的长度,若不存在公共子序列,则输出文件仅有一行输出一个整数0,否则在输出文件的第二行输出所求得的最长公共子序列(也用一个大写字母组成的字符串表示。 【输入样例】 ABCBDAB BDCBA 【输出样例】 4 BCBA 【问题分析】 这个问题也是相当经典的。。 这个题目的阶段很不明显,所以初看这个题目没什么头绪,不像前面讲的有很明显的上一步,上一层之类的东西,只是两个字符串而且互相没什么关联。 但仔细分析发现还是有入手点的: 既然说是动态规划,那我们首先要考虑的就是怎么划分子问题,一般对于前面讲到的街道问题和数塔问题涉及走向的,考虑子问题时当然是想上一步是什么?但这个问题没有涉及走向,也没有所谓的上一步,该怎么办呢? 既然是求公共子序列,也就有第一个序列的第i个字符和第二个序列的第j个字符相等的情况。 那么我们枚第一个序列(X)的字符,和第二个序列(Y)的字符。 显然如果X[i]=Y[j]那么起点是1(下面说的子序列都是起点为1的),长度为i的子序列和长度为j的子序列的最长公共子序列就是长度为i-1和长度为j-1 的子序列中最长的公共子

最长公共子序列问题

实验三最长公共子序列问题 1.实验环境 本实验采用 java 语言编写实现,环境:,编译器: eclipse 2.实验目的 通过最长公共子序列问题,巩固并详细分析动态规划思想和解题 步骤。 3.设计思路 最长公共子序列的定义为:设有两个序列S[1..m]和9[仁n],需要寻找它们之间的一个最长公共子序列。 例如,假定有两个序列: S1: I N T H E B E G I N N I N G S2: A L L T H I N G S A R E L O S T 则S i和S的一个最长公共子序列为 THING又比如: S1: A B C B D A B S2: B D C A B A 则它们的一个最长公共子序列为 BCBA。 这里需要注意的是,一个子序列不一定必须是连续的,即中间可被其他字符分开,单它们的顺序必须是正确的。另外,最长公共子序列不一定只有一个,而我们需要寻找的是其中一个。

当然,如果要求子序列里面的元素必须连成一片也是可以的。实际上,连成一片的版本比这里实现的更容易。 4.过程 我们可以通过蛮力策略解决这个问题,步骤如下: 1.检查S1[1..m]里面每一个子序列。 2.看看其是否也是S2[1..n]里的子序列。 3.在每一步记录当前找到的子序列里面最长的子序列。 这种方法的效率十分低下。因此本实验采用动态规划的方法实现该算法。 利用动态规划寻找最长公共子序列步骤如下: 1.寻找最长公共子序列的长度。 2.扩展寻找长度的算法来获取最长公共子序列。 策略:考虑序列S1和S2的前缀序列。 设 c[i,j] = |LCS (S1[1..i],S2[1..j]),则有 c[m, n] = |LCS(S1 S2)| 所以有 c[ i -1 , j -1 ] + 1, 如要 S1[i] = S2[j] c[i, j]= max{ c [ i - 1, j ], c[ i , j -1 ] }, 如果 S1[i]工S2[j] 然后回溯输出最长公共子序列过程:

第7讲 城乡规划法(一)(2011年新版)

第三章城乡规划法 大纲要求 3.《中华人民共和国城乡规划法》 3.1了解《中华人民共和国城乡规划法》立法背景 3.2熟悉《中华人民共和国城乡规划法》的重要意义与作用 3.3掌握《中华人民共和国城乡规划法》内容与说明 新版教材的变动 第三节《<城乡规划法>主要内容》中“城乡规划的实施原则”新增在城乡规划确定的建设用地以外不得作出规划许可的原则。“城乡规划实施管理制度”新增临时建设和临时用地规划管理。“规划修改的报审程序”新增城市、县、镇人民政府修改近期建设规划的情形。“城乡规划的法律责任”新增违反《城乡规划法》构成犯罪行为的处理办法。 授课时间 本章大约需要一讲的时间。 《中华人民共和国城乡规划法》是我国社会主义现代化建设新时期,适应新形势需要,为加强城乡规划管理,协调城乡空间布局,改善人居环境,涉及城乡建设和发展全局,促进城乡经济社会全面、协调、可持续发展而制定的一部基本法。该法经2007年10月28日第十届全国人民代表大会常务委员会第三十次会议通过并颁布,自2008年1月1日起施行。 一、立法指导思想、背景和重要意义 1、立法指导思想 制定《城乡规划法》的指导思想是:按照贯彻落实科学发展观和构建社会主义和谐社会的要求,统筹城乡建设和发展,确立科学的规划体系和严格的规划实施制度,正确处理近期建设与长远发展、局部利益与整体利益、经济发展与环境保护、现代化建设与历史文化保护等关系,促进合理布局,节约资源,保护环境,体现特色,充分发挥城乡规划在引导城镇化健康发展、促进城乡经济社会可持续发展中的统筹协调和综合调控作用。 2、立法背景 《城乡规划法》是由建设部起草的。它总结了1990年4月1日起施行的《城市规划法》和1993年11月1日起施行的《村庄和集镇规划建设管理条例》的实施经验,结合我国城镇化发展战略实行以来城市经

最长公共子序列实验报告

最长公共子序列问题 一.实验目的: 1.加深对最长公共子序列问题算法的理解,实现最长公共子序列问题的求解算法; 2.通过本次试验掌握将算法转换为上机操作; 3.加深对动态规划思想的理解,并利用其解决生活中的问题。 二.实验内容: 1.编写算法:实现两个字符串的最长公共子序列的求解; 2.将输入与输出数据保存在文件之中,包括运行时间和运行结果; 3.对实验结果进行分析。 三.实验操作: 1.最长公共子序列求解: 将两个字符串放到两个字符型数组中,characterString1和characterString2,当characterString1[m]= characterString2[m]时,找出这两个字符串m之前的最长公共子序列,然后在其尾部加上characterString1[m],即可得到最长公共子序列。当characterString1[m] ≠characterString2[m]时,需要解决两个子问题:即找出characterString1(m-1)和characterString2的一个最长公共子序列及characterString1和characterString2(m-1)的一个最长公共子序列,这两个公共子序列中较长者即为characterString1和characterString2的一个最长公共子序列。 2.动态规划算法的思想求解: 动态规划算法是自底向上的计算最优值。 计算最长公共子序列长度的动态规划算法LCS-Length以characterString1和characterString2作为输入,输出两个数组result和judge1,其中result存储最长公共子序列的长度,judge1记录指示result的值是由那个子问题解答得到的,最后将最终的最长公共子序列的长度记录到result中。 以LCS-Length计算得到的数组judge1可用于快速构造序列最长公共子序列。首先从judge1的最后开始,对judge1进行配对。当遇到“↖”时,表示最长公共子序列是由characterString1(i-1)和characterString2(j-1)的最长公共子序列在尾部加上characterString1(i)得到的子序列;当遇到“↑”时,表示最长公共子序列和characterString1(i-1)与characterString2(j)的最长公共子序列相同;当遇到“←”时,表示最长公共子序列和characterString1(i)与characterString2(j-1)的最长公共子序列相同。 如图所示:

中华人民共和国城乡规划法 解读

中华人民共和国城乡规划法解读对比旧版《城市规划法》~《城乡规划法》有哪些变化, 对比旧版《城市规划法》~最大的不同是强调城乡统筹~最显著的进展是强化监督职能~最明确的要求是落实政府责任。 《城乡规划法》共七章七十条~与《城市规划法》比较~取消 了“城市新区开发和旧区改造”这一章~新增加了“城乡规划的 修改”和“监督检查”两个章节。 中华人民共和国城乡规划法 ,2007年10月28日第十届全国人民代表大会常务委员会第三十次会议通过, 目录 第一章总则 第二章城乡规划的制定 第三章城乡规划的实施 第四章城乡规划的修改 第五章监督检查 第六章法律责任 第七章附则 第一章总则 《城乡规划法》的重要内容可概括为十个方面: 第一~突出城乡规划的公共政策属性。《城乡规划法》明确提 出:为了加强城乡规划管理~协调城乡空间布局~改善人居环境~ 促进城乡经济社会全面、协调、可持续发展~制定本法。从内容上看~重视资源节约、环境保护、文化与自然遗产保护,促进公共财政首先投到基础设施、公共

设施项目,强调城乡规划制定、实施全过程的公众参与,保证公平~明确了有关赔偿或补偿责任。第二~强调城乡规划综合调控的地位和作用。《城乡规划法》指出:“任何单位和个人都应当遵守依法批准并公布的城乡规划~服从规划管理”。这就从法律上明确~城乡规划是政府引导和调控城乡建设和发展的一项重要公共政策~是具有法定地位的发展蓝图。同时~法律适用范围扩大~强调城乡统筹、区域统筹,确立先规划后建设的原则,“三规合一”是规划未来发展的必然趋势。第三~新的城乡规划体系的建立。体现了一级政府、一级规划、一级事权的规划编制要求,明确规划的强制性内容,突出近期建设规划的地位,强调规划编制责任。 第四~严格城乡规划修改程序。对城乡规划评估~修改省域城镇体系规划、城市体规划、镇总体规划~修改详细规划等~都做出了详细的规定。 第五~城乡规划行政许可制度的完善。建立完善了针对土地有偿使用制度和投资体制改革的建设用地规划管理制度,规定了各项城乡规划的行政许可。 第六~对行政权力的监督制约。明确了上级行政部门的监督~人民代表大会的监督~以及全社会的公众监督。 第七~对城乡规划编制单位提出了新的要求。对城乡规划编制单 位的资质管理~对规划师职业的管理~都有明确规定。第八~加强人民代表大会的监督作用。省域城镇体系规划、城市和县城关镇总体规划由本级人大常委会审议~镇总体规划由人大审议。城市控制性详细规划报本级人大常委会备案~县城关镇控制性详细规划报县人大常委会备案。省域城镇体系规划、城市和镇总体规划定期评估须向人大报告。 第九~强化法律责任。追究政府和行政人员的责任,追究城乡规划编制单位的责任,追究违法建设行为的责任,明确对违法行为给予罚款的范围和数额,授予市政府强制拆除权。 第十~法律授权~建立完善的城乡规划法律体系。

动态规划算法举例分析

动态规划算法 1. 动态规划算法介绍 基本思想是将待求解问题分解成若干子问题,先求解子问题,最后用这些子问题带到原问题,与分治算法的不同是,经分解得到的子问题往往是不是相互独立,若用分治则子问题太多。 2. 适用动态规划算法问题的特征 (1)最优子结构 设计动态规划算法的第一步骤通常是要刻画最优解的结构。当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。问题的最优子结构性质提供了该问题可用动态规划算法求解的重要线索。 在动态规划算法中,问题的最优子结构性质使我们能够以自底向下的方式递归地从子问题的最优解逐步构造出整个问题的最优解。同时,它也使我们能在相对小的子问题空间中考虑问题。 (2)重叠子问题 可用动态规划算法求解的问题应具备的另一基本要素是子问题的重叠性质。在用递归算法自顶向下解此问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只有简单地用常数时间查看一下结果。通常,不同的子问题个数随输入问题的大小呈多项式增长。因此,用动态规划算法通常只需要多项式时间,从而获得较高的解题效率。 (3)备忘录方法

动态规划算法的一个变形是备忘录方法。备忘录方法也是一个表格来保存已解决的子问题的答案,在下次需要解此子问题时,只要简单地查看该子问题的解答,而不必重新计算。与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。 备忘录方法为每个子问题建立一个记录项,初始化时,该记录项存入一个特殊的值,表示该子问题尚未求解。在求解过程中,对每个待求的子问题,首先查看其相应的记录项。若记录项中存储的是初始化时存入的特殊值,则表示该子问题是第一次遇到,则此时计算出该子问题的解,并保存在其相应的记录项中。若记录项中存储的已不是初始化时存入的特殊值,则表示该子问题已被计算过,其相应的记录项中存储的是该子问题的解答。此时,只要从记录项中取出该子问题的解答即可。 3. 基本步骤 a 、找出最优解的性质,并刻画其结构特征。 b 、递归地定义最优值。 c 、以自底向上的方式计算出最优值。 d 、根据计算最优值时得到的信息构造一个最优解。(可省) 例1-1 [0/1背包问题] [问题描述] 用贪心算法不能保证求出最优解。在0/1背包问题中,需要对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为i w ,价 值为 i v 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳 装载是指所装入的物品价值最高,即∑=n i i i x v 1 取得最大值。约束条件为 c x w n i i i ≤∑=1 , {}() n i x i ≤≤∈11,0。

动态规划算法及其应用

湖州师范学院实验报告 课程名称:算法 实验二:动态规划方法及其应用 一、实验目的 1、掌握动态规划方法的基本思想和算法设计的基本步骤。 2、应用动态规划方法解决实际问题。 二、实验内容 1、问题描述 1 )背包问题 给定 N 种物品和一个背包。物品 i 的重量是 C i ,价值为 W i ;背包的容量为 V。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?在选择装入背包的物品,对每种物品只有两个选择:装入或不装入,且不能重复装入。输入数据的第一行分别为:背包的容量 V,物品的个数 N。接下来的 N 行表示 N 个物品的重量和价值。输出为最大的总价值。 2)矩阵连乘问题 给定 n 个矩阵:A1,A2,...,An,其中 Ai 与 Ai+1 是可乘的,i=1 , 2... , n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。 3 )LCS问题 给定两个序列,求最长的公共子序列及其长度。输出为最长公共子序列及其长度。 2、数据输入:文件输入或键盘输入。 3、要求: 1)完成上述两个问题,时间为 2 次课。 2)独立完成实验及实验报告。 三、实验步骤 1、理解方法思想和问题要求。 2、采用编程语言实现题目要求。 3、上机输入和调试自己所写的程序。 4、附程序主要代码: (1) #include int max(int a, int b) { return (a > b)? a : b; } int knapSack(int W, int wt[], int val[], int n) { if (n == 0 || W == 0) return 0;

动态规划法求解最长公共子序列(含Java代码)

公共子序列问题徐康123183 一.算法设计 假设有两个序列X和Y,假设X和Y分别有m和n个元素,则建立一个二维数组C[(m+1)*(n+1)],记录X i与Y j的LCS的长度。将C[i,j]分为三种情况: 若i =0 或j =0时,C[i,j]=0; 若i,j>0且X[i]=Y[j],C[i,j]=C[i-1,j-1]+1; 若i,j>0且X[i] Y[j],C[i,j]=max{C[i-1,j],C[i,j-1]}。 再使用一个m*n的二维数组b,b[i,j]记录C[i,j]的来向: 若X[i]=Y[j],则B[i,j]中记入“↖”,记此时b[i,j] = 1; 若X[i] Y[j]且C[i-1,j] > C[i,j-1],则b[i,j]中记入“↑”,记此时B[i,j] = 2; 若X[i] Y[j]且C[i-1,j] < C[i,j-1],则b[i,j]中记入“←”,记此时B[i,j] = 3; 若X[i]Y[j]且C[i-1,j] = C[i,j-1],则b[i,j]中记入“↑”或“←”,记此时B[i,j] = 4; 得到了两个数组C[]和B[],设计递归输出LCS(X,Y)的算法: LCS_Output(Direction[][], X[], i, j, len,LCS[]){ If i=0 or j=0 将LCS[]保存至集合LCS_SET中 then return; If b[i,j]=1 then /*X[i]=Y[j]*/ {LCS_Output(b,X,i-1,j-1); 将X[i]保存至LCS[len-i];} else if b[i,j]=2 then /*X[i]Y[j]且C[i-1,j]>C[i,j-1]*/ LCS_Output(b,X,i-1,j) else if b[i,j]=3 then /*X[i]Y[j]且C[i-1,j]

相关文档
最新文档