1 / 17

算法设计与分析 第三章 动态规划

算法设计与分析 第三章 动态规划. 杨圣洪. 3.3 最长公共子序列. 概述: 若给定序列 X={x 1 ,x 2 ,…,x m } ,取其 连续 或 不连续 部分字符串,称为 子串 或 子序列 。 ( 板 ) 如序列 X={A , B , C , B , D , A , B} ,则 Z={B , C , D , B} 是 X 的子序列,其下标序列为 {2 , 3 , 5 , 7} ,显然不是 X 中连续字符串。 若 Z 既是 X 的子序列,又是 Y 的子序列,则称 Z 是序列 X 和 Y 的 公共子序列 。 ( 板 )

chase
Télécharger la présentation

算法设计与分析 第三章 动态规划

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 算法设计与分析第三章 动态规划 杨圣洪

  2. 3.3 最长公共子序列 • 概述: • 若给定序列X={x1,x2,…,xm},取其连续或不连续部分字符串,称为子串或子序列。(板) • 如序列X={A,B,C,B,D,A,B},则Z={B,C,D,B}是X的子序列,其下标序列为 {2,3,5,7},显然不是X中连续字符串。 • 若Z既是X的子序列,又是Y的子序列,则称Z是序列X和Y的公共子序列。(板) • 问题:给定序列X={x1,x2,…,xm}和Y={y1, y2, …,yn},如何找出X和Y的最长公共子序列。

  3. 3.3 最长公共子序列 请找出下列两个序列的最长公共子序列 X={A,B,C,B,D,A,B} (板) Y={B,D,C,A,B,A} (板) 提示: 回忆离散中子集的生成方法? 生成各自所有子串,则2m2n,一一比对,指数级! 是否可你一个我一个的找呢? 请把你的思路详细描述之。

  4. 分治法的基本思想 • 分治法的基本思想 • 将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。 • 对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。 • 将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。 • 将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

  5. T(n) T(n) T(n) n = n = n = T(n/2) T(n/2) T(n/2) T(n/2) n/2 n/2 n/2 n/2 n/2 n/2 n/2 n/2 T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) T(n/4) 动态规划算法 • 动态规划算法也是将待求解问题分解成若干个子问题。 • 分治法要求子问题互相独立。子问题数目太多,最后T(n)可能指数级。有些子问题被重复计算。 • 动态规划保存已解决的子问题的答案,需要时引用,避免重复计算,从而T(n)为多项式时间。

  6. 动态规划基本步骤 • 找出最优解的性质,并刻划其结构特征。判断整体最优是否有局部最优 • 递归定义最优值。有难度。 • 以自底向上的方式计算出最优值。非递归 • 根据计算最优值时得到的信息,构造最优解。!

  7. 全局最优局部最优? • 设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,则Z是Xm-1和Y的最长公子串 • 若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公子串 • 因此Z是整体最长公共子序列时,其部分也是是X与Y的前面部分中的最优子串。 • 满足“全局最优局部最优”特点,具有最优子结构性质,可动态规划。

  8. 全局最优局部最优? • X={x1,x2,…,xm}和Y={y1,y2,…,yn},最长公共子序列Z={z1, z2, …, zk} ,则 若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列 • 反证法求证zk=xm=yn。假设zk xm。 • 由于X、Y的最后字符xm=yn,而Z此时已经是X、Y公共子串,故Z+'xm'=Z+'yn'也是X,Y公共子串,其长度=Z长+1>Z长,与Z最长矛盾。 • 反证法求证“Zk-1是Xm-1和Yn-1的最长公共子序列” • 假设Zk-1不是Xm-1,Yn-1的最长公共子串, W 是Xm-1,Yn-1的最长公共子串, • 则|W|>|Zk-1|即|W|k,而X,Y的最后字符相同, • 故W+'xm'为X,Y的公共子串,其长=|W|+1k+1, • 而前面已知X,Y的最长公共子串长为k.故矛盾

  9. 全局最优局部最优? • 设X={x1,x2,…,xm}和Y={y1,y2,…,yn},其最长公共子序列Z={z1,z2,…,zk} ,则: • (1)若xm=yn(最后者同则必属公串),则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。 • (2)若xm≠yn且xm≠zk,则Z是Xm-1和Y最长公子串 • (3)若xm≠yn且zk≠yn,则Z是X和Yn-1最长公子串 • 证(2):知Z是{x1,x2,…,xm-1,xm},Y最长子串且长为k • 又zkxm即Z与{x1,x2,…,xm-1,xm} 的最后字符xm不同 • 故Z是{x1,x2,…,xm-1},Y公共子串 • 假设“Xm-1与Y有长>k”的公共子串W,则|W|>k • 因X,Y最后字符不同即xmyn,则“Xm-1,Y的公共子串W”也是X,Y的公共子串。即X,Y公子串长为k+1 • 而X,Y的最长公共子串长为k,故矛盾。

  10. 算法描述 • 若xm=yn(最后者同则必属公串),则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。 • 若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公子串 • 若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公子串 • 算法基本思想:其实递归 分治与动规都要这步 • 当xm=yn(最后者同)时, maxStr(Xm-1,Yn-1)+xm(=yn)得maxStr(X,Y)。 (板) • 当xm  yn(最后者异)时, maxStr(Xm-1,Yn), maxStr( Xm,Yn-1) 中较长者为maxStr(X,Y)。 (板) • 总之,计算maxStr(X,Y) ,要算maxStr(Xm-1,Yn-1), maxStr(Xm-1,Yn), maxStr(Xm,Yn-1) (板) • maxStr(Xm-1,Yn-1)公共子问题, • 重叠可备忘,每个问题都算到可动态规划

  11. 子问题的递归结构 • 递归关系: 序列X的前缀Xi ={x1,x2,…,xi}, 序列Y的前缀Yj ={y1,y2,…,yj}。 • c[i][j]保存Xi与Yj的最长公共子序列的长度。 • 当i=0或j=0时即空序列,故C[0][j]=0或C[i][0]=0 。此处c[i][j],两变元(i,j),m[i][j] • 递归: x[i]=y[j]各退1否单退1最大者(板C示算)

  12. 计算最优值 • c[i][j]的下标取值范围可知,共有θ(mn)个不同的子问题,每个子问题都会算到,故动态规划算法自底向上,比备忘递归法效率更高。 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++) //X的第1个字符~最后一个 for (j = 1; j <= n; j++) { //针对X[i],Y从第1个~最后一个 if (x[i]==y[j]) { //(Xn,Yn)=(Xn-1,Yn-1)的公串+xn. c[i][j]=c[i-1][j-1]+1; b[i][j]=1; } else if (c[i-1][j]>=c[i][j-1]) { //(Xm,Yn)=(Xm-1,Yn) c[i][j]=c[i-1][j]; b[i][j]=2;} else { //(Xm,Yn)=(Xm,Yn-1) c[i][j]=c[i][j-1]; b[i][j]=3; } } } //在js中b,c为全局变量,未出现在形参中

  13. 1对角前,2上行同列, 3同行左列 4,构造最长公共子序列 • 根据b[i][j]构造最长公子串。 • 算法描述: void LCS(int i,int j,char *x,int **b) { if (i ==0 || j==0) return; if (b[i][j]== 1){ //(Xn,Yn)=(Xn-1,Yn-1)的公串+xn. LCS(i-1,j-1,x,b); cout<<x[i]; } else if (b[i][j]== 2){ //(Xm,Yn)=(Xm-1,Yn) LCS(i-1,j,x,b);} else { //(Xm,Yn)=(Xm,Yn-1) LCS(i,j-1,x,b);} }

  14. 算法的改进 • 在算法lcsLength和lcs中,可进一步将数组b省去。 • c[i][j]的值仅由c[i-1][j-1],c[i-1][j]和c[i][j-1] 确定。 • 对于给定的数组元素c[i][j],可以不借助于数组b而仅借助于c本身在时间内确定c[i][j]的值是由c[i-1][j-1],c[i-1][j]和c[i][j-1]中哪一个值所确定的。 • 如果只需要计算最长公共子序列的长度,则算法的空间需求可大大减少。事实上,在计算c[i][j]时,只用到数组c的第i行和第i-1行。因此,用2行的数组空间就可以计算出最长公共子序列的长度。进一步的分析还可将空间需求减至O(min(m,n))。

  15. 计算最优值 • 不要数组B void LCSLengthB(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++) //X的第1个字符~最后一个 for (j = 1; j <= n; j++) { //针对X[i],Y从第1个~最后一个 if (x[i]==y[j]) { //(Xn,Yn)=(Xn-1,Yn-1)的公串+xn. c[i][j]=c[i-1][j-1]+1;} //b[i][j]=1; else if (c[i-1][j]>=c[i][j-1]) { //(Xm,Yn)=(Xm-1,Yn) c[i][j]=c[i-1][j];} //b[i][j]=2; else { //(Xm,Yn)=(Xm,Yn-1) c[i][j]=c[i][j-1];} // b[i][j]=3; } }

  16. 算法的改进 • 在算法lcsLength和lcs中,将数组b省去。 void LCSB(int i,int j,char *x,int **b) { if (i ==0 || j==0) return; if (c[i][j]==c[i-1][j-1]+1){ //(Xn,Yn)=(Xn-1,Yn-1) +xn. LCSB(i-1,j-1,x,b); cout<<x[i]; } else if (c[i-1][j]>c[i][j-1]){ //(Xm,Yn)=(Xm-1,Yn) LCSB(i-1,j,x,b);} else { //(Xm,Yn)=(Xm,Yn-1) LCSB(i,j-1,x,b);} }

  17. 算法的改进 • 改lcs返回最长公子串 String LCSC(int i,int j,char *x,int **b) { if (i ==0 || j==0) return ""; if (c[i][j]==c[i-1][j-1]+1){ //(Xn,Yn)=(Xn-1,Yn-1) +xn. return LCSC(i-1,j-1,x,b)+x[i]; } else if (c[i-1][j]>c[i][j-1]){ //(Xm,Yn)=(Xm-1,Yn) return LCSC(i-1,j,x,b);} else { //(Xm,Yn)=(Xm,Yn-1) return LCSC(i,j-1,x,b);} }

More Related