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

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

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

    走在架構(gòu)師的大道上 Jack.Wang's home

    Java, C++, linux c, C#.net 技術(shù),軟件架構(gòu),領(lǐng)域建模,IT 項(xiàng)目管理 Dict.CN 在線詞典, 英語(yǔ)學(xué)習(xí), 在線翻譯

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
     

    計(jì)算字符串相似度的簡(jiǎn)易算法

    算法設(shè)計(jì)背景:

    最近設(shè)計(jì)知識(shí)管理系統(tǒng)的資源導(dǎo)入功能,為了盡量的做到組件化,方便擴(kuò)展,方便其他模塊使用。簡(jiǎn)化組件提供的和需要的接口,設(shè)計(jì)并實(shí)現(xiàn)了基于 Mapping 機(jī)制的導(dǎo)入框架。其中有一功能用到了計(jì)算兩個(gè)字符串相似度的算法,簡(jiǎn)單設(shè)計(jì)如下以便參考:

    設(shè)計(jì)思想:

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

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

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

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

    針對(duì)于 jackbllogjackblog 只需要?jiǎng)h除一個(gè)或增加一個(gè) l 就可以把兩個(gè)字符串變?yōu)橄嗤?。把這種操作需要的次數(shù)定義為兩個(gè)字符串的距離 L, 則相似度定義為 1/(L+1) 即距離加一的倒數(shù)。那么jackbllogjackblog的相似度為 1/1+1=1/2=0.5 也就是所兩個(gè)字符串的相似度是 0.5,說(shuō)明兩個(gè)字符串已經(jīng)很接近啦。

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

     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




    本博客為學(xué)習(xí)交流用,凡未注明引用的均為本人作品,轉(zhuǎn)載請(qǐng)注明出處,如有版權(quán)問(wèn)題請(qǐng)及時(shí)通知。由于博客時(shí)間倉(cāng)促,錯(cuò)誤之處敬請(qǐng)諒解,有任何意見(jiàn)可給我留言,愿共同學(xué)習(xí)進(jìn)步。
    posted on 2009-01-19 23:53 Jack.Wang 閱讀(11010) 評(píng)論(9)  編輯  收藏 所屬分類: 開(kāi)發(fā)技術(shù) 、數(shù)學(xué)&算法

    Feedback

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法 2009-01-20 09:37 Anonymous
    看看算法書(shū)再來(lái)吧  回復(fù)  更多評(píng)論
      

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法[未登錄](méi) 2009-01-20 10:44 IceRao
    使用向量吧。  回復(fù)  更多評(píng)論
      

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法 2009-01-20 10:59 夜弓
    字符串不是字節(jié)流
    相似度是不好這樣簡(jiǎn)單算的
    比如
    helloworld
    hollywood
    9個(gè)字母里面就有6個(gè)相同
    顯然不是那么簡(jiǎn)單回事  回復(fù)  更多評(píng)論
      

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

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

    從編輯距離本身的定義角度,我覺(jué)得還是不適合作為字符串相似的量度的,但可以作為輔助手段來(lái)對(duì)可能的錯(cuò)誤輸入產(chǎn)生提示。  回復(fù)  更多評(píng)論
      

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法 2009-01-20 20:21 Jack.Wang
    這么多人回復(fù)??!
    @Anonymous
    恩,說(shuō)的很好,謝謝啦!之前沒(méi)看相關(guān)的算法書(shū),只是有這個(gè)想法!順便寫(xiě)了寫(xiě)!應(yīng)該有更好的量度來(lái)計(jì)算兩個(gè)字符串的相似度!等看看算法書(shū)或者有 blog 友貼貼!  回復(fù)  更多評(píng)論
      

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法 2009-08-29 23:41 cricket
    遞歸算法的復(fù)雜度非常高,動(dòng)態(tài)規(guī)劃算法能把復(fù)雜度降到O(M*N),改進(jìn)后能到O(N+K^2),自動(dòng)機(jī)和bit-parallelism算法甚至能到O(N)  回復(fù)  更多評(píng)論
      

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法 2009-10-14 14:54 yeluolei
    有那么簡(jiǎn)單么……  回復(fù)  更多評(píng)論
      

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

    # re: 計(jì)算字符串相似度的簡(jiǎn)易算法 2010-03-25 09:18 szx
    老大,這是《編程之美》上的原題源代碼  回復(fù)  更多評(píng)論
      

    主站蜘蛛池模板: 亚洲激情校园春色| 免费看又黄又无码的网站| 久艹视频在线免费观看| 噼里啪啦电影在线观看免费高清| 亚洲Av无码乱码在线观看性色| 亚洲AV无码不卡在线播放| 亚洲最大中文字幕无码网站| 精品一区二区三区免费观看| 成人网站免费观看| 亚洲第一极品精品无码久久| 狼人大香伊蕉国产WWW亚洲| 国产99视频精品免费专区| 日韩免费视频网站| 亚洲黄色免费观看| 一级毛片a免费播放王色| 思思久久99热免费精品6| 国产精品一区二区三区免费| 黄页网站在线看免费| 中文字幕中韩乱码亚洲大片| 亚洲jjzzjjzz在线观看| 中文字幕在线免费看线人| 成人免费视频国产| 亚洲色欲www综合网| 国产免费内射又粗又爽密桃视频 | a毛片免费全部播放完整成| 成年女人色毛片免费看| 亚洲国产精品第一区二区| 亚洲乱码中文字幕小综合| 中文字幕无码免费久久9一区9| 四虎成人免费大片在线| 亚洲视频在线视频| 在线看片免费人成视频久网下载| 国产无遮挡又黄又爽免费视频| 亚洲综合免费视频| 国产色无码精品视频免费| 黄网站色在线视频免费观看| 亚洲国产精品无码久久SM| 国产精品手机在线亚洲| 国内免费高清在线观看| 亚洲欧洲综合在线| 久9久9精品免费观看|