算法导论——动态规划之最长公共子序列(LCS)和最长回文子序列(LPS)
2015-09-09 20:46
309 查看
有两个字符串A和B,假设为A=”abcbdab”,B=”bdcaba”;最长公共子序列(LCS)问题指的时找到A和B的一个公共的子串C,C的长度要是最长。
在这里我们很明显的发现最长子序列为”bcba”
用动态规划的思想来考虑这个问题:
若A={a1,a2,a3,…,am},B={b1,b2,b3,…,bn},Z={z1,z2,z3,…,zk}是A和B的任意LCS
1.如果am==bn,那么zk=am=bn,且Z(0…k-1)是A(0…m-1)和B(0…n-1)的一个LCS
2.若am!=bn,则Z(0…k)是A(0…m-1)和B(0…n)的一个LCS或者是A(0…m)和B(0…n-1)的一个LCS
所以可以推出以下公式:
c[i,j]=0,当i=0或j=0;
c[i,j]=c[i-1,j-1]+1,当i,j>0且Ai==Bj;
c[i,j]=max(c[i-1,j),c[i,j-1]),当i,j>0且Ai!=Bj;
感觉理解的也不是很深,本文是自己的一个学习过程
最长回文子序列(LPS)
一个字符数组S=“character”,回文序列为”carac”
要求S(i,j) 之间的回文序列长度c[i,j],
1.当Si==Sj ,这里要考虑当i+1==j的情况,若i+1==j,c[i,j]=2;否则c[i,j]=c[i+1,j-1]+1,
2.当Si!=Sj,c[i,j]=max{c[i+1,j],c[i,j-1]};
在这里我们很明显的发现最长子序列为”bcba”
用动态规划的思想来考虑这个问题:
若A={a1,a2,a3,…,am},B={b1,b2,b3,…,bn},Z={z1,z2,z3,…,zk}是A和B的任意LCS
1.如果am==bn,那么zk=am=bn,且Z(0…k-1)是A(0…m-1)和B(0…n-1)的一个LCS
2.若am!=bn,则Z(0…k)是A(0…m-1)和B(0…n)的一个LCS或者是A(0…m)和B(0…n-1)的一个LCS
所以可以推出以下公式:
c[i,j]=0,当i=0或j=0;
c[i,j]=c[i-1,j-1]+1,当i,j>0且Ai==Bj;
c[i,j]=max(c[i-1,j),c[i,j-1]),当i,j>0且Ai!=Bj;
感觉理解的也不是很深,本文是自己的一个学习过程
public class LCS { //Longest common subsequence public static void main(String[] args){ char[] A=("abcbdab").toCharArray(); char[] B="bdcaba".toCharArray(); int[][] c,b; c=new int[A.length+1][B.length+1]; b=new int[A.length+1][B.length+1]; for(int i=0;i<A.length;i++){ c[i][0]=0; } for(int i=0;i<B.length;i++){ c[0][i]=0; } for(int i=1;i<=A.length;i++){ for(int j=1;j<=B.length;j++){ if(A[i-1]==B[j-1]){ c[i][j]=c[i-1][j-1]+1; b[i][j]=2; }else{ if(c[i][j-1]>c[i-1][j]){ c[i][j]=c[i][j-1]; b[i][j]=3; }else{ c[i][j]=c[i-1][j]; b[i][j]=1; } } } } printLCS(A,b,A.length,B.length); } public static void printLCS(char[] A,int[][] b,int i,int j){ if(i==0||j==0) return; if(b[i][j]==2){ printLCS(A,b,i-1,j-1); System.out.println(A[i-1]); }else if(b[i][j]==1){ printLCS(A,b,i-1,j); } else printLCS(A,b,i,j-1); } }
最长回文子序列(LPS)
一个字符数组S=“character”,回文序列为”carac”
要求S(i,j) 之间的回文序列长度c[i,j],
1.当Si==Sj ,这里要考虑当i+1==j的情况,若i+1==j,c[i,j]=2;否则c[i,j]=c[i+1,j-1]+1,
2.当Si!=Sj,c[i,j]=max{c[i+1,j],c[i,j-1]};
public class LPS { // 最长回文子序列 static int[][] c; static int[][] b; public static void main(String args[]) { char[] s = "aa".toCharArray(); c = new int[s.length][s.length]; b = new int[s.length][s.length]; for (int i = 0; i < s.length; i++) c[i][i] = 1; findLPS(s, 0, s.length - 1); System.out.println(c[0][s.length - 1]); printLPS(s, 0, s.length - 1); } public static void printLPS(char[] s, int p, int q) { if (p == q) System.out.print(s[p]); else { if (b[p][q] == 2) { if (p + 1 == q) { System.out.print(s[p] +""+ s[p]); } else { System.out.print(s[p]); printLPS(s, p + 1, q - 1); System.out.print(s[p]); } } else if (b[p][q] == 1) { printLPS(s, p + 1, q); } else printLPS(s, p, q - 1); } } public static int findLPS(char[] s, int p, int q) { if (p == q) return 1; if (c[p][q] > 1) return c[p][q]; if (s[p] == s[q]) { if (p + 1 == q) c[p][q] = 2; else c[p][q] = findLPS(s, p + 1, q - 1) + 2; b[p][q] = 2; } else { int m1 = findLPS(s, p + 1, q); int m2 = findLPS(s, p, q - 1); if (m1 > m2) { c[p][q] = m1; b[p][q] = 1; } else { c[p][q] = m2; b[p][q] = 3; } } return c[p][q]; } }
相关文章推荐
- POJ - 1287 Networking(最小生成树模板题)
- 为什么解析 array_column不可用,
- 第一天:探索(2)
- Web前端——JQuery的进阶(测试使用 jQuery进行指定的操作)
- Codechef September Challenge 2015
- 有return的情况下try catch finally的执行顺序
- list.h 解析
- role 'PLUSTRACE' does not exist
- WSDL2java简单使用
- 用枚举器遍历数组倒序输出数组和给数组元素排序
- 书签去重
- list.h 解析
- <Chapter 2>2-1-2.安装Java SDK
- java 自动拆箱(unboxing)和自动装箱(boxing)
- Convert Single Instance to RAC – Part 2: Manually Convert to RAC
- Android视频播放手动切换和自动切换横竖屏冲突问题
- 在线教学系统:C#实现网络电子白板、课件功能
- 文件上传
- Http请求和相应模式(B/S)(1)
- Socket通信:简单传输到增加多线程进行多数据传输