<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    走在架構師的大道上 Jack.Wang's home

    Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
     

    計算字符串相似度的簡易算法

    算法設計背景:

    最近設計知識管理系統的資源導入功能,為了盡量的做到組件化,方便擴展,方便其他模塊使用。簡化組件提供的和需要的接口,設計并實現了基于 Mapping 機制的導入框架。其中有一功能用到了計算兩個字符串相似度的算法,簡單設計如下以便參考:

    設計思想:

       把兩個字符串變成相同的基本操作定義如下:

    1.     修改一個字符(如把 a 變成 b

    2.     增加一個字符 ( abed 變成 abedd)

    3.     刪除一個字符(如 jackbllog 變成 jackblog

    針對于 jackbllogjackblog 只需要刪除一個或增加一個 l 就可以把兩個字符串變為相同。把這種操作需要的次數定義為兩個字符串的距離 L, 則相似度定義為 1/(L+1) 即距離加一的倒數。那么jackbllogjackblog的相似度為 1/1+1=1/2=0.5 也就是所兩個字符串的相似度是 0.5,說明兩個字符串已經很接近啦。

    任意兩個字符串的距離都是有限的,都不會超過他們的長度之和,算法設計中我們并不在乎通過一系列的修改后,得到的兩個相同字符串是什么樣子。所以每次只需一步操作,并遞歸的進行下一計算。JAVA 的實現如下:

     1/**
     2 * 
     3 */

     4package org.blogjava.arithmetic;
     5
     6import java.util.HashMap;
     7import java.util.Map;
     8
     9/**
    10 * @author jack.wang
    11 * 
    12 */

    13public class StringDistance {
    14
    15    public static final Map<String, String> DISTANCE_CACHE = new HashMap<String, String>();
    16
    17    private static int caculateStringDistance(byte[] firstStr, int firstBegin,
    18            int firstEnd, byte[] secondStr, int secondBegin, int secondEnd) {
    19        String key = makeKey(firstStr, firstBegin, secondStr, secondBegin);
    20        if (DISTANCE_CACHE.get(key) != null{
    21            return Integer.parseInt(DISTANCE_CACHE.get(key));
    22        }
     else {
    23            if (firstBegin >= firstEnd) {
    24                if (secondBegin >= secondEnd) {
    25                    return 0;
    26                }
     else {
    27                    return secondEnd - secondBegin + 1;
    28                }

    29            }

    30            if (secondBegin >= secondEnd) {
    31                if (firstBegin >= firstEnd) {
    32                    return 0;
    33                }
     else {
    34                    return firstEnd - firstBegin + 1;
    35                }

    36            }

    37            if (firstStr[firstBegin] == secondStr[secondBegin]) {
    38                return caculateStringDistance(firstStr, firstBegin + 1,
    39                        firstEnd, secondStr, secondBegin + 1, secondEnd);
    40            }
     else {
    41                int oneValue = caculateStringDistance(firstStr, firstBegin + 1,
    42                        firstEnd, secondStr, secondBegin + 2, secondEnd);
    43                int twoValue = caculateStringDistance(firstStr, firstBegin + 2,
    44                        firstEnd, secondStr, secondBegin + 1, secondEnd);
    45                int threeValue = caculateStringDistance(firstStr,
    46                        firstBegin + 2, firstEnd, secondStr, secondBegin + 2,
    47                        secondEnd);
    48                DISTANCE_CACHE.put(key, String.valueOf(min(oneValue, twoValue,
    49                        threeValue) + 1));
    50                return min(oneValue, twoValue, threeValue) + 1;
    51            }

    52        }

    53    }

    54
    55    public static float similarity(String stringOne, String stringTwo) {
    56        return 1f / (caculateStringDistance(stringOne.getBytes(), 0, stringOne
    57                .getBytes().length - 1, stringTwo.getBytes(), 0, stringOne
    58                .getBytes().length - 1+ 1);
    59    }

    60
    61    private static int min(int oneValue, int twoValue, int threeValue) {
    62        return oneValue > twoValue ? twoValue
    63                : oneValue > threeValue ? threeValue : oneValue;
    64    }

    65
    66    private static String makeKey(byte[] firstStr, int firstBegin,
    67            byte[] secondStr, int secondBegin) {
    68        StringBuffer sb = new StringBuffer();
    69        return sb.append(firstStr).append(firstBegin).append(secondStr).append(
    70                secondBegin).toString();
    71    }

    72
    73    /**
    74     * @param args
    75     */

    76    public static void main(String[] args) {
    77        float i = StringDistance.similarity("jacklovvedyou""jacklodveyou");
    78        System.out.println(i);
    79    }

    80}

    81




    本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
    posted on 2009-01-19 23:53 Jack.Wang 閱讀(11006) 評論(9)  編輯  收藏 所屬分類: 開發技術數學&算法

    Feedback

    # re: 計算字符串相似度的簡易算法 2009-01-20 09:37 Anonymous
    看看算法書再來吧  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法[未登錄] 2009-01-20 10:44 IceRao
    使用向量吧。  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2009-01-20 10:59 夜弓
    字符串不是字節流
    相似度是不好這樣簡單算的
    比如
    helloworld
    hollywood
    9個字母里面就有6個相同
    顯然不是那么簡單回事  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2009-01-20 16:29 Anonymous
    計算編輯距離是個好想法,但還是有局限性的

    另外你的相似度計算公式從分布上并不很natural,比如兩個長度在30的單詞,如果編輯距離為1,他們的相似度會比兩個長度在5編輯距離為1的單詞要更加高一些(我覺得這樣的想法會更natural一點)。

    從編輯距離本身的定義角度,我覺得還是不適合作為字符串相似的量度的,但可以作為輔助手段來對可能的錯誤輸入產生提示。  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2009-01-20 20:21 Jack.Wang
    這么多人回復啊!
    @Anonymous
    恩,說的很好,謝謝啦!之前沒看相關的算法書,只是有這個想法!順便寫了寫!應該有更好的量度來計算兩個字符串的相似度!等看看算法書或者有 blog 友貼貼!  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2009-08-29 23:41 cricket
    遞歸算法的復雜度非常高,動態規劃算法能把復雜度降到O(M*N),改進后能到O(N+K^2),自動機和bit-parallelism算法甚至能到O(N)  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2009-10-14 14:54 yeluolei
    有那么簡單么……  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2009-12-17 14:02 黃凱
    是的,使用編輯距離(尤其是改良后的Levenshtein算法)其算法復雜度可以縮短至O(2k+1)。不過lz的思想和Levenshtein算法的初衷本質上是一致的,還是值得贊賞的,可惜人家比你早很多年提出來~  回復  更多評論
      

    # re: 計算字符串相似度的簡易算法 2010-03-25 09:18 szx
    老大,這是《編程之美》上的原題源代碼  回復  更多評論
      

    主站蜘蛛池模板: 亚洲av永久无码精品天堂久久| 亚洲av无码潮喷在线观看 | 亚洲精品无码AV人在线播放| 男女猛烈激情xx00免费视频| 免费播放特黄特色毛片| 免费福利资源站在线视频| 亚洲国产高清在线一区二区三区| 免费人成再在线观看网站| 久久亚洲精品无码观看不卡| 中文字幕av免费专区| 亚洲国产精品国自产拍电影| 8x8×在线永久免费视频| 亚洲娇小性色xxxx| 日本免费人成黄页网观看视频| 亚洲aⅴ无码专区在线观看| 亚洲第一视频在线观看免费| 男女拍拍拍免费视频网站| 久久精品国产精品亚洲艾| 91热成人精品国产免费| 亚洲精品美女久久7777777| 男人的天堂亚洲一区二区三区 | 午夜亚洲av永久无码精品| 国产精品免费看久久久香蕉| 久久亚洲综合色一区二区三区| 在线观看免费av网站| 亚洲中文字幕乱码AV波多JI| 免费吃奶摸下激烈视频| 国产成人久久AV免费| 亚洲熟妇久久精品| 亚洲天堂中文字幕在线| 91精品导航在线网址免费| 亚洲av综合av一区二区三区 | 亚洲Av永久无码精品黑人| 狠狠亚洲婷婷综合色香五月排名| 久久精品免费观看国产| 亚洲AV综合色区无码一二三区 | 成年男女免费视频网站| www免费插插视频| 亚洲成a人片77777群色| 大胆亚洲人体视频| 亚洲综合免费视频|