隨筆 - 25  文章 - 32  trackbacks - 0
          <2009年2月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          1234567

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          由于本人對算法理解的重大失誤,造成原來寫的程序有重大BUG。特此向各位道歉來了,呵呵
          今天又將算法看了一遍,終于理解其精髓
          下面是主要的實現(xiàn)代碼,獻(xiàn)丑了
          首先是初始化一個boolean數(shù)組,存放各個字符是否匹配的:
              public static boolean[][] getCompareBooleanArray(String source,
                      String compareTo) {
                  
          boolean[][] comps;
                  
          if (compareTo == null || source == null) {
                      
          throw new IllegalArgumentException("必須設(shè)置完兩個文本后再進行初始化");
                  }
                  comps 
          = new boolean[compareTo.length()][source.length()];
                  
          for (int i = 0; i < compareTo.length(); i++) {
                      
          for (int j = 0; j < source.length(); j++) {
                          comps[i][j] 
          = compareTo.charAt(i) == source.charAt(j);
                          
          // System.out.print(comps[i][j] + "\t");
                      }
                      
          // System.out.println();
                  }
                  
          return comps;
              }
          這個實現(xiàn)基本上沒什么說的,就這樣

          接著是一個根據(jù)這個boolean數(shù)組初始化一個int矩陣的函數(shù),這個函數(shù)就對應(yīng)尋找最大匹配路徑的函數(shù)
              public static int[][] getSetpPathArr(boolean[][] barr) {
                  
          int[][] iarr = new int[barr.length][barr[0].length];
                  
          for (int i = barr.length - 1; i >= 0; i--) {
                      
          for (int j = barr[i].length - 1; j >= 0; j--) {
                          
          int v_i_j = barr[i][j] ? 1 : 0;
                          
          int n_i_1_j_1 = i + 1 >= iarr.length || j + 1 >= iarr[i].length ? 0
                                  : iarr[i 
          + 1][j + 1];
                          
          int n_i_1_j = i + 1 >= iarr.length ? 0 : iarr[i + 1][j];
                          
          int n_i_j_1 = j + 1 >= iarr[i].length ? 0 : iarr[i][j + 1];
                          
          int v_n_1_1 = v_i_j + n_i_1_j_1;
                          iarr[i][j] 
          = v_n_1_1 > n_i_1_j ? v_n_1_1 > n_i_j_1 ? v_n_1_1
                                  : n_i_j_1 : n_i_1_j 
          > n_i_j_1 ? n_i_1_j : n_i_j_1;
                      }
                  }
                  
          return iarr;
              }
          根據(jù)算法的解釋,從下往上,從右向左計算每個格子

          對應(yīng)尋找最優(yōu)路徑的函數(shù),也是初始化一個int[][]
              public static int[][] getMinSetpArr(int[][] miarr, boolean[][] barr) {
                  
          int[][] iarr = new int[miarr.length][miarr[0].length];
                  
          for (int i = iarr.length - 1; i >= 0; i--) {
                      
          for (int j = iarr[i].length - 1; j >= 0; j--) {
                          
          if (barr[i][j]) {
                              iarr[i][j] 
          = getV(iarr, i + 1, j + 1+ 1;
                          } 
          else if (getV(miarr, i, j + 1>= getV(miarr, i + 1, j)) {
                              iarr[i][j] 
          = getV(iarr, i, j + 1);
                          } 
          else {
                              iarr[i][j] 
          = getV(iarr, i + 1, j) + 1;
                          }
                      }
                  }
                  
          return iarr;
              }
          這樣就相應(yīng)對應(yīng)了算法中講的那三個矩陣。
          當(dāng)然了,上面有調(diào)用到一個叫g(shù)etV的方法,方法很簡單
              private static int getV(int[][] arr, int i, int j) {
                  
          if (i >= arr.length || j >= arr[i].length) {
                      
          return 0;
                  }
                  
          return arr[i][j];
              }
          分別初始化完這三個數(shù)組后對結(jié)果進行計算。
          boolean[][] barr = getCompareBooleanArray(source, compareTo);
                  
          int[][] miarr = getSetpPathArr(barr);
                  
          int[][] diarr = getMinSetpArr(miarr, barr);
          先找出從頂點出發(fā),下一步該走的那幾個點:
          List<Point> points = new ArrayList<Point>();
                  
          int maxJ = -1;
                  
          for (int i = 0; i < barr.length; i++) {
                      
          int tempMaxJ = -1;
                      
          for (int j = 0; j < barr[i].length; j++) {
                          
          if (j > maxJ && maxJ != -1) {
                              
          break;
                          }
                          
          if (barr[i][j]) {
                              
          if (tempMaxJ == -1) {
                                  tempMaxJ 
          = j;
                              }
                              points.add(
          new Point(i, j));
                          }
                      }
                      
          if (tempMaxJ != -1) {
                          maxJ 
          = tempMaxJ;
                      }
                  }
          找出可能的最大最優(yōu)匹配路徑,這個可能會有幾條路徑,核心代碼:
          int max = 0;
                  
          int minSetp = -1;
                  
          for (Point point : points) {
                      
          if (miarr[point.getX()][point.getY()] > max) {
                          max 
          = miarr[point.getX()][point.getY()];
                      }
                  }
                  
          for (Point point : points) {
                      
          if (minSetp == -1) {
                          minSetp 
          = diarr[point.getX()][point.getY()];
                      } 
          else if (miarr[point.getX()][point.getY()] >= max
                              
          && diarr[point.getX()][point.getY()] < minSetp) {
                          minSetp 
          = diarr[point.getX()][point.getY()];
                      }
                  }
                  List
          <Point> willRemove = new ArrayList<Point>();
                  
          for (Point point : points) {
                      
          if (miarr[point.getX()][point.getY()] < max
                              
          || diarr[point.getX()][point.getY()] > minSetp) {
                          willRemove.add(point);
                      }
                  }
                  points.removeAll(willRemove);
                  willRemove.clear();
          找到這里,最大匹配并且最優(yōu)匹配的路徑就找到了
          下面就是要計算差異了,基本和我上次寫的計算差異的方法差不多
          List<TextDiff> diffs = new ArrayList<TextDiff>();
                  
          if (points.size() >= 1) {
                      Point startPoint 
          = points.get(0);
                      points.clear();

                      
          if (startPoint.getX() != 0) {
                          diffs.add(
          new TextDiff(TextDiff.TYPE_INSERTED, 0, startPoint
                                  .getX()));
                      }
                      
          if (startPoint.getY() != 0) {
                          diffs.add(
          new TextDiff(TextDiff.TYPE_DELETED, 0, startPoint
                                  .getY()));
                      }
                      Point next 
          = getNext(startPoint, miarr, diarr, barr);
                      
          while (next != null) {
                          
          if (!barr[startPoint.getX()][startPoint.getY()]) {
                              startPoint 
          = new Point(startPoint.getX() + 1, startPoint
                                      .getY() 
          + 1);
                          }
                          
          if (startPoint.getX() != next.getX() - 1
                                  
          || startPoint.getY() != next.getY() - 1) {
                              diffs.add(
          new TextDiff(TextDiff.TYPE_INSERTED, startPoint
                                      .getX(), next.getX() 
          - startPoint.getX()));

                              diffs.add(
          new TextDiff(TextDiff.TYPE_DELETED, startPoint
                                      .getY(), next.getY() 
          - startPoint.getY()));
                          }
                          startPoint 
          = next;
                          next 
          = getNext(startPoint, miarr, diarr, barr);
                      }
                      
          if (startPoint.getX() != barr.length) {
                          diffs.add(
          new TextDiff(TextDiff.TYPE_INSERTED, startPoint
                                  .getX(), barr.length 
          - startPoint.getX()));
                      }
                      
          if (startPoint.getY() != barr[0].length) {
                          diffs.add(
          new TextDiff(TextDiff.TYPE_DELETED,
                                  startPoint.getY(), barr[
          0].length - startPoint.getY()));
                      }
                  }

          大功告成。。。。。
          源碼:http://www.aygfsteel.com/Files/phyeas/src.zip
          posted on 2009-02-15 13:22 phyeas 閱讀(1066) 評論(3)  編輯  收藏

          FeedBack:
          # re: 文本比較算法的實現(xiàn)2 2010-04-29 17:03 sfply
          似乎還是不對

          symptoms reflux could.
          ssreflux could eventually.
          你用這兩個字符串比較,得到的結(jié)果不是正確的;  回復(fù)  更多評論
            
          # re: 文本比較算法的實現(xiàn)2 2010-04-29 17:12 sfply
          不好意思,是對的:)
          @sfply
            回復(fù)  更多評論
            
          # re: 文本比較算法的實現(xiàn)2 2010-04-29 18:50 sfply
          稍稍有一點瑕疵,盼博主能夠解決;

          比如有兩個字符串
          s1 = "symptoms, reflux";
          s2 = "symptoms, untreated reflux";

          進行比較時,s1在前面和在后面,比較的結(jié)果是不一樣的,效果如下:
          symptoms, untreated reflux
          symptoms, __________reflux

          symptoms, ___re_______flux
          symptoms, untreated reflux

          實際上,第一種結(jié)果是正確的,因為reflux是一個整體,而在第二種結(jié)果中,re被前面的字符串干擾了;

          請教如何解決這種問題;
            回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 屯昌县| 化德县| 庆阳市| 金门县| 鄢陵县| 克东县| 吕梁市| 长垣县| 科尔| 和顺县| 无锡市| 商河县| 晋江市| 蕉岭县| 会泽县| 洛川县| 宜良县| 新泰市| 靖江市| 泾阳县| 白玉县| 旌德县| 五家渠市| 湘潭县| 抚顺县| 黔江区| 奉贤区| 天柱县| 长汀县| 巴里| 大厂| 鹰潭市| 湟中县| 平遥县| 明光市| 邻水| 临桂县| 苗栗县| 临汾市| 上虞市| 浦江县|