2011年6月6日 星期一

Java LCS 最長共同子序列


import java.util.Scanner;

public class LongComSub {
    public static String str1;
    public static String str2;
    public static String result;//記錄共同子序列
 
    public static char [] cha1;
    public static char [] cha2;
 
    public static int [][] array;//LCS表格
    public static String [][] prev;//記錄計算方向
 
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
  
        System.out.print("輸入第一個字串: ");
        str1 = sc.nextLine();
        System.out.print("輸入第二個字串: ");
        str2 = sc.nextLine();
  
        /*str1為短字串  str2為長字串*/
        if(str1.length() > str2.length()){
              String value = str1;
              str1 = "0" + str2;
              str2 = "0" + value;
        }
        else{
              str1 = "0" + str1;
              str2 = "0" + str2;
        }
 
        /*設定陣列長度*/
        array = new int[str1.length()][str2.length()];
        prev = new String[str1.length()][str2.length()];
  
        /*將字串轉換為陣列*/
        cha1 = str1.toCharArray();
        cha2 = str2.toCharArray();
  
        setZero();
  
        countLCS();

        foundValue(cha1.length-1,cha2.length-1);
  
        System.out.print("最長共同子序列: ");
        StringBuffer sb = new StringBuffer(result.substring(4));
        System.out.print(sb.reverse());
    }
 
    /*將 array[x][0] 和 array[0][x] 都設為 0*/
    public static void setZero(){
        for(int i = 0; i < str1.length(); i++){
              array[i][0] = 0;
        } 
        for(int i = 0; i < str2.length(); i++){
              array[0][i] = 0;
        }
    }
 
    /*計算並製作LCS表格*/
    public static void countLCS(){
        System.out.print("  ");
        for(int u = 0; u < cha2.length; u++){
              System.out.print(cha2[u] + " ");
        }
        System.out.println();

        for(int i = 1; i < cha1.length; i++){
              System.out.print(cha1[i] + " ");
              for(int j = 1; j < cha2.length; j++){
                    if( i == 0 || j == 0 ){
                          System.out.print(array[i][j] + " ");
                          continue;
                    }
                    if( cha1[i] == cha2[j] ){
                          array[i][j] = array[i-1][j-1] + 1;
                          prev[i][j] = "左上方";
                          System.out.print(array[i][j] + " ");
                    }
                    else if( array[i-1][j] < array[i][j-1]){
                          array[i][j] = array[i][j-1];
                          prev[i][j] = "左方";
                          System.out.print(array[i][j] + " ");
                    }
                    else{
                          array[i][j] = array[i-1][j];
                          prev[i][j] = "上方";
                          System.out.print(array[i][j] + " ");
                    }
              }
        }
    }
 
    /*找出LCS值*/
    public static void foundValue(int a,int b){
        if(a == 0 && b == 0){
              System.exit(0);
        }
  
        if(prev[a][b] == "左上方"){
              //String初始值null,所以會從null開使加字串
              result += Character.toString(cha1[a]);
              foundValue(a-1,b-1);
        }
        else if(prev[a][b] == "上方"){
              foundValue(a-1,b);
        }
        else if(prev[a][b] == "左方"){
              foundValue(a,b-1);
        }
    }
}


沒有考慮到時間複雜度以及記憶體問題唷