乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【串和序列處理 6】LCS 最長公共子序列

       靜聽沙漏 2012-01-08

      LCS:又稱最長公共子序列。其中子序列(subsequence)的概念不同于串的子串。它是一個不一定連續(xù)但按順序取自字符串X中的字符序列。例如:串"AAAG"就是串“CGATAATTGAGA”的一個子序列。

      字符串的相似性問題可以通過求解兩個串間的最長公共子序列(LCS)來得到。當然如果使用窮舉算法列出串的所有子序列,一共有2^n種,而每個子序列是否是另外一個串的子序列又需要O(m)的時間復雜度,因此這個窮舉的方法時間復雜度是O(m*(2^n))指數(shù)級別,效率相當?shù)目膳?。我們采用動態(tài)規(guī)劃算法來解決這個問題。

      動態(tài)規(guī)劃算法解決最長公共子序列

      假如我們有兩個字符串:X=[0,1,2....n] Y=[0,1,2...m]。我們定義L(i, j)為X[0...i]與Y[0...j]之間的最長公共子序列的長度。通過動態(tài)規(guī)劃思想(復雜問題的最優(yōu)解是子問題的最優(yōu)解和子問題的重疊性質(zhì)決定的)。我們考慮這樣兩種情況:

      (1) 當X[i]=Y[j]時, L(i, j)=L(i-1, j-1)+1。證明很簡單。

      (2) 當X[i]!=Y[j]時,說明此事X[0...i]和Y[0...j]的最長公共子序列中絕對不可能同時含有X[i]和Y[j]。那么公共子序列可能以X[i]結(jié)尾,可能以Y[j]結(jié)尾,可以末尾都不含有X[i]或Y[j]。因此

      L(i, j)= MAX{L(i-1 , j), L(i, j-1)}

      LCS動態(tài)規(guī)劃Java源代碼

      Java代碼
      1. package net.hr.algorithm.string;
      2. /**
      3. * 最長公共子串LCS
      4. * @author heartraid
      5. */
      6. public class LCS {
      7. /**字符串X的字符數(shù)組*/
      8. private char[] charArrayX=null;
      9. /**字符串Y的字符數(shù)組*/
      10. private char[] charArrayY=null;
      11. public LCS(String sa,String sb){
      12. charArrayX=new char[sa.length()+1];
      13. System.arraycopy(sa.toCharArray(),0,charArrayX,1,sa.length());
      14. charArrayY=new char[sb.length()+1];
      15. System.arraycopy(sb.toCharArray(),0,charArrayY,1,sb.length());
      16. }
      17. /**
      18. * 得到最長公共子序列的長度
      19. */
      20. public void getLCS(){
      21. int[][] length=new int[charArrayX.length+1][charArrayY.length+1];
      22. for(int m=1;m<charArrayX.length;m++)
      23. for(int n=1;n<charArrayY.length;n++){
      24. if(charArrayX[m]==charArrayY[n]){
      25. length[m][n]=length[m-1][n-1]+1;
      26. }
      27. else
      28. length[m][n]=max(length[m-1][n],length[m][n-1]);
      29. }
      30. //打印最長公共子序列
      31. String lcstr="";
      32. int x=charArrayX.length-1;
      33. int y=charArrayY.length-1;
      34. while(x>=1&&y>=1){
      35. if(charArrayX[x]==charArrayY[y]){
      36. lcstr=charArrayX[x]+lcstr;
      37. x--;
      38. y--;
      39. }else{
      40. if(length[x-1][y]<=length[x][y-1])
      41. y--;
      42. else
      43. x--;
      44. }
      45. }
      46. System.out.println("最長公共子序列為:"+lcstr+" [length="+lcstr.length()+"]");
      47. }
      48. /**
      49. * 取最大值
      50. */
      51. private int max(int m,int n){
      52. return m>n?m:n;
      53. }
      54. /**
      55. * 測試
      56. */
      57. public static void main(String[] args) {
      58. LCS lcs=new LCS("GTTCCTAATA","CGATAATTGAGA");
      59. lcs.getLCS();
      60. }
      61. }

      這里解釋一下上面的代碼,其中getLength()的作用是遞歸獲取最長公共子串的長度,并得到遞歸過程中每個子串之間最長公共子串長度的狀態(tài)表lcs[][],這張表運行的結(jié)果如下:

      C G A T A A T T G A G A

      0 0 0 0 0 0 0 0 0 0 0 0 0
      G 0 0 1 1 1 1 1 1 1 1 1 1 1
      T 0 0 1 1 2 2 2 2 2 2 2 2 2
      T 0 0 1 1 2 2 2 3 3 3 3 3 3
      C 0 1 1 1 2 2 2 3 3 3 3 3 3
      C 0 1 1 1 2 2 2 3 3 3 3 3 3
      T 0 1 1 1 2 2 2 3 4 4 4 4 4
      A 0 1 1 2 2 3 3 3 4 4 5 5 5
      A 0 1 1 2 2 3 4 4 4 4 5 5 6
      T 0 1 1 2 3 3 4 5 5 5 5 5 6
      A 0 1 1 2 3 4 4 5 5 5 6 6 6

      紅色數(shù)字的位置就揭示了最長公共子序列: CTATTA。也就是說分析這張表就可以得到最長公共子序列字符串。

      為什么呢?因為通過表的回溯過程,從后向前重構(gòu)了一個最長公共子序列。對于任何位置lcs[i][j],確定是否X[i]=Y[j]。如果是,那么X[i]必是最長公共子序列的一個字符。如果否,那么移動到lcs[i,j-1]和lcs[i-1, j]之間的較大者。

      動態(tài)規(guī)劃方法LCS效率:

      動態(tài)規(guī)劃方法構(gòu)造最長公共子序列需要O(m*n)的代價,另外,如果想要得到最長公共子序列,又需要O(m+n)的時間來讀取csl[][]數(shù)組。盡管如此,其時間復雜度仍然比蠻力窮舉的指數(shù)級別要強的多。

      問題拓展:設A,B,C是三個長為n的字符串,它們?nèi)∽酝怀?shù)大小的字母表。設計一個找出三個串的最長公共子串的O(n^3)的時間算法。(來自《Algorithm Design》(中文版:算法分析與設計) - Chapter9 - 文本處理 - 創(chuàng)新題C-9.18)

      分析:可以通過《LCS最長公共子序列》的動態(tài)規(guī)劃算法,設計Java源代碼如下:

      Java代碼 復制代碼 收藏代碼
      1. public class TriLCS{
      2. char[] charA=null;
      3. char[] charB=null;
      4. char[] charC=null;
      5. public TriLCS(String sa,String sb,String sc){
      6. charA=new char[sa.length()+1];
      7. System.arraycopy(sa.toCharArray(),0,charA,1,sa.length());
      8. charB=new char[sb.length()+1];
      9. System.arraycopy(sb.toCharArray(),0,charB,1,sb.length());
      10. charC=new char[sc.length()+1];
      11. System.arraycopy(sc.toCharArray(),0,charC,1,sc.length());
      12. }
      13. public void getTriLCS(){
      14. int[][][] length=new int[charA.length][charB.length][charC.length];
      15. for(int a=1;a<charA.length;a++)
      16. for(int b=1;b<charB.length;b++)
      17. for(int c=1;c<charC.length;c++){
      18. if(charA[a]==charB[b]&&charA[a]==charC[c]){
      19. length[a][b][c]=length[a-1][b-1][c-1]+1;
      20. }
      21. else if(charA[a]==charB[b]&&charA[a]!=charC[c]){
      22. length[a][b][c]=max(length[a-1][b-1][c],length[a][b][c-1]);
      23. }
      24. else if(charA[a]==charC[c]&&charA[a]!=charB[b]){
      25. length[a][b][c]=max(length[a-1][b][c-1],length[a][b-1][c]);
      26. }
      27. else if(charB[b]==charC[c]&&charA[a]!=charB[b]){
      28. length[a][b][c]=max(length[a][b-1][c-1],length[a-1][b][c]);
      29. }
      30. else{
      31. length[a][b][c]=max(length[a-1][b][c],length[a][b-1][c],length[a][b][c-1],length[a-1][b-1][c],length[a-1][b][c-1],length[a][b-1][c-1]);
      32. }
      33. }
      34. //打印最長公共子序列
      35. String lcstr="";
      36. int a=charA.length-1;
      37. int b=charB.length-1;
      38. int c=charC.length-1;
      39. while(a>=1&&b>=1&&c>=1){
      40. if(charA[a]==charB[b]&&charA[a]==charC[c]){
      41. lcstr=charA[a]+lcstr;
      42. a--;
      43. b--;
      44. c--;
      45. }
      46. else if(charA[a]==charB[b]&&charA[a]!=charC[c]){
      47. if(length[a-1][b-1][c]<=length[a][b][c-1])
      48. c--;
      49. else{
      50. a--;
      51. b--;
      52. }
      53. }
      54. else if(charA[a]==charC[c]&&charA[a]!=charB[b]){
      55. if(length[a-1][b][c-1]<=length[a][b-1][c])
      56. b--;
      57. else{
      58. a--;
      59. c--;
      60. }
      61. }
      62. else if(charB[b]==charC[c]&&charA[a]!=charB[b]){
      63. if(length[a][b-1][c-1]<=length[a-1][b][c])
      64. a--;
      65. else{
      66. b--;
      67. c--;
      68. }
      69. }
      70. else{
      71. int maxize=max(length[a-1][b][c],length[a][b-1][c],length[a][b][c-1],length[a-1][b-1][c],length[a-1][b][c-1],length[a][b-1][c-1]);
      72. if(maxize==length[a-1][b][c])
      73. a--;
      74. if(maxize==length[a][b-1][c])
      75. b--;
      76. if(maxize==length[a][b][c-1])
      77. c--;
      78. if(maxize==length[a-1][b-1][c]){
      79. a--;
      80. b--;
      81. }
      82. if(maxize==length[a-1][b][c-1]){
      83. a--;
      84. c--;
      85. }
      86. if(maxize==length[a][b-1][c-1]){
      87. b--;
      88. c--;
      89. }
      90. }
      91. }
      92. System.out.println("最長子串為:"+lcstr+"(length="+length[charA.length-1][charB.length-1][charC.length-1]+")");
      93. }
      94. /**
      95. * 取最大值
      96. */
      97. private int max(int m,int n){
      98. return m>n?m:n;
      99. }
      100. /**
      101. * 取最大值
      102. */
      103. private int max(int x,int y,int z,int k,int m,int n){
      104. int maxizen=0;
      105. if(maxizen<x) maxizen=x;
      106. if(maxizen<y) maxizen=y;
      107. if(maxizen<z) maxizen=z;
      108. if(maxizen<k) maxizen=k;
      109. if(maxizen<m) maxizen=m;
      110. if(maxizen<n) maxizen=n;
      111. return maxizen;
      112. }
      113. public static void main(String[] args){
      114. TriLCS tri=new TriLCS("aadsbbbcs","adsabcs","adbsbsdcs");
      115. tri.getTriLCS();
      116. }
      117. }

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多