1. 程式人生 > >計算字串相似度

計算字串相似度

問題描述:

有兩個不同的字串,通過使用一套操作方法可以把兩個字串變成一樣的。

例如:

1)  "a" 和 "b"  ==>  把a變成b,或把b變成a  變化了一次
2)  "abc" 和 "ade"  ==>  把bc變成de,或把de變成bc  變化了兩次
3)  "abcd" 和 "abcde"  ==>  刪除e  變化了一次

每操作一次,兩個字串的距離就加 1。

1)  "a" 和 "b" 的距離為 1
2)  "abc" 和 "ade"  的距離為 2
3)  "abcd" 和 "abcde" 的距離為 1

相似度為距離的倒數。


思考方法:


1  使用遞迴的思考方式:



字串A和B,假設A中的一個字元和B中的一個字元比較後不一樣。

可以使用下面幾種操作將它們變為一樣的:
    -    修改 A的字元
    -    修改 B的字元
    -    刪除 A的字元
    -    刪除 B的字元
    -    增加 A中的一個字元
    -    增加 B中的一個字元


因為只需要計算字串間的距離,所以並不需要記錄具體的操作形式,但無論怎樣操作,A和B的距離增加了 1。

t1   ==>  遞迴時,考慮A串不動,操作B串
t2   ==>  遞迴時,考慮B串不動,操作A串
t3   ==>  遞迴時,考慮同時操作A串和B串


int calc_distance(char* strA, int nABegin, int nAEnd, char* strB, int nBBegin, int nBEnd)
{
    if (strA[nABegin] == strB[nBBegin])
    {
        return calc_distance(strA, nABegin+1, nAEnd, strB, nBBegin+1, nBEnd);
    }
    else
    {
        t1 = calc_distance(strA, nABegin, nAEnd, strB, nBBegin+1, nBEnd);
        t2 = calc_distance(strA, nABegin+1, nAEnd, strB, nBBegin, nBEnd);
        t3 = calc_distance(strA, nABegin+1, nAEnd, strB, nBBegin+1, nBEnd);


        min = minval(t1,t2,t3)+1;
        return min;
    }
}



2  使用動態規劃的思考方式:

用  記錄分別對字串A和B同時操作

record[x][y-1]       ==>  用來記錄,考慮A串不動,操作B串後的操作次數
record[x-1][y]       ==>  用來記錄,考慮B串不動,操作A串後的操作次數
record[x-1][y-1]   ==>  用來記錄,考慮同時操作A串和B串的操作次數

然後取其中最小的值 加 1 賦值給  record[x][y]。這樣經過操作後record[lenA][lenB]就是最後的結果。

int calc_distance2(char* strA, int lenA, char* strB, int lenB)
{
    int** record = NULL;
    int i = 0, j = 0;
    int ret = 0;
    record = new int*[lenA+1];
    for (i = 0; i < lenA+1; i++)
    {
        record[i] = new int[lenB+1];
        memset(record[i],0,sizeof(int)*(lenB+1));
    }

    for (i = 1; i <= lenA; i++)
    {
        record[i][0] = i;
    }
    for (j = 1; j <= lenB; j++)
    {
        record[0][j] = j;
    }
    record[0][0] = 0;
    for (i = 1; i <= lenA; i++)
        for (j = 1; j <= lenB; j++)
        {
            if (strA[i-1] == strB[j-1])
            {
                record[i][j] = record[i-1][j-1];
            }
            else
            {
                record[i][j] = minval(record[i-1][j-1], record[i][j-1], record[i-1][j]) + 1;
            }
        }

    ret = record[lenA][lenB];
    for (i = 0; i < lenA+1; i++)
    {
        delete[] record[i];
    }
    delete[] record;

    return ret;
}

程式碼:


#include <iostream>
using namespace std;

int minval(int a, int b, int c)
{
    int min = 0;
    if (a < b)
    {
        if (c < a)
            min = c;
        else
            min = a;
    }
    else
    {
        if (c < b)
            min = c;
        else
            min = b;
    }
    return min;
}

int calc_distance1(char* strA, int nABegin, int nAEnd, char* strB, int nBBegin, int nBEnd)
{
    int t1 = 0, t2 = 0, t3 = 0;
    int min = 0;
    if (nABegin > nAEnd)
    {
        (nBBegin > nBEnd) ? min = 0: min = nBEnd - nBBegin + 1;
        return min;
    }

    if (nBBegin > nBEnd)
    {
        (nABegin > nAEnd) ? min = 0: min = nAEnd - nABegin + 1;
        return min;
    }

    cout << "compare: " << strA[nABegin] << ":" << strB[nBBegin] << endl;
    if (strA[nABegin] == strB[nBBegin])
    {
        return calc_distance1(strA, nABegin+1, nAEnd, strB, nBBegin+1, nBEnd);
    }
    else
    {
        t1 = calc_distance1(strA, nABegin, nAEnd, strB, nBBegin+1, nBEnd);
        t2 = calc_distance1(strA, nABegin+1, nAEnd, strB, nBBegin, nBEnd);
        t3 = calc_distance1(strA, nABegin+1, nAEnd, strB, nBBegin+1, nBEnd);

        min = minval(t1,t2,t3)+1;
        return min;
    }
}

int calc_distance2(char* strA, int lenA, char* strB, int lenB)
{
    int** record = NULL;
    int i = 0, j = 0;
    int ret = 0;

    record = new int*[lenA+1];
    for (i = 0; i < lenA+1; i++)
    {
        record[i] = new int[lenB+1];
        memset(record[i],0,sizeof(int)*(lenB+1));
    }

    for (i = 1; i <= lenA; i++)
    {
        record[i][0] = i;
    }
    for (j = 1; j <= lenB; j++)
    {
        record[0][j] = j;
    }

    record[0][0] = 0;
    for (i = 1; i <= lenA; i++)
        for (j = 1; j <= lenB; j++)
        {
            if (strA[i-1] == strB[j-1])
            {
                record[i][j] = record[i-1][j-1];
            }
            else
            {
                record[i][j] = minval(record[i-1][j-1], record[i][j-1], record[i-1][j]) + 1;
            }
        }

    ret = record[lenA][lenB];
    for (i = 0; i < lenA+1; i++)
    {
        delete[] record[i];
    }
    delete[] record;
    return ret;
}

void main()
{
    int dist = 0;
    //char* testA = "abc";
    //char* testB = "abcd";

    //char* testA = "abce";
    //char* testB = "abcd";

    //char* testA = "abcwyz";
    //char* testB = "abcmno";

    char* testA = "a1b2c3d4";
    char* testB = "abcd";

    //char* testA = "xxa1b2c3d4";
    //char* testB = "abcd";

    int lenA = strlen(testA);
    int lenB = strlen(testB);

    //dist = calc_distance1(testA, 0, lenA-1, testB, 0, lenB-1);
    dist = calc_distance2(testA, lenA, testB, lenB);

    cout << "A=" << testA << "  B=" << testB << "   distance=" << dist << endl;
    cin >> dist;
}






















相關推薦

計算字串相似的一些方法

產品出了一個奇怪的需求,想通過字串相似度取匹配城市= =(當然,最後證實通過字串相似度取判斷兩個字串是不是一個城市是不對的!!!) 這裡就記錄一下我計算字串(英文字串)相似度的方法吧~ 參考文件: L

LeetCode之計算字串相似或編輯距離EditDistance

問題描述: /** * Given two words word1 and word2, find the minimum number of steps required to * convert word1 to word2. (each oper

java實現編輯距離演算法,計算字串相似

 這是Levenshtein Distance演算法的java實現,另外oracle 10g r2當中好像自帶了這樣的函式,utl_match包當中public class LD {  /**       * 計算向量距離       * Levenshtein Distan

計算字串相似

問題描述:有兩個不同的字串,通過使用一套操作方法可以把兩個字串變成一樣的。 例如: 1)  "a" 和 "b"  ==>  把a變成b,或把b變成a  變化了一次 2)  "abc" 和 "ade"  ==>  把bc變成de,或把de變成bc  變化了兩次

計算兩個字串相似的演算法

該方法是使用的Levenshtein演算法的一個實現。  簡單介紹下Levenshtein Distance(LD):LD 可能衡量兩字串的相似性。它們的距離就是一個字串轉換成那一個字串過程中的新增、刪除、修改數值。     舉例: 如果str1="test",st

C字串相似計算

     #region 計算相似度         /// <summary>         /// 取最小的一位數         /// </summary>         /// <param name="first"><

判斷兩字串相似

/** * <h5>功能:判斷兩字串相似度(最小為0,最大為1)</h5> * * @param strOne * @param strTwo * @return 兩字串相似度(最小為0,最大為1) */ public static double SimlaritySt

字串相似演算法

字串相似度演算法 一、百度百科 二、用途 三、實現過程 四、JAVA程式碼實現 五、原理 六、結束語 一、百度百科 Levenshtein 距離,又稱編輯距離,指的是兩個字串之間,由一個轉換

用gensim doc2vec計算文字相似,Python可以跑通的程式碼

Python3.7版本,轉載自:https://blog.csdn.net/juanjuan1314/article/details/75124046 wangyi_title.txt檔案下載地址:連結:https://pan.baidu.com/s/1uL75P13t98YHMqgv3Kx7T

簡單的字串相似匹配加排序

今天遇到一個問題,需要將一組字串,跟結果需要的字串相比較,根據相似性排列出來,思考了一個下午,想了一個簡易的匹配演算法,寫出程式碼的時候下班了,回家除錯了幾次後就成功了,特此將該演算法寫出來。 思路:將一組字串儲存到list中,用兩個for迴圈,先

python比較字串相似

python自帶比較相似度的模組,difflib。比較兩個字串的模組是difflib.SequenceMatcher,使用起來很簡單: import difflibdef string_similar(s1, s2): return difflib.SequenceMatcher(None,

Java程式碼實現餘弦相似演算法比較兩字串相似

因工作需要比較兩個兩個字串的相似度比較,由於最短編輯距離演算法不符合需求,就又找其他演算法,在網上看到了另一個演算法:餘弦相似度演算法。於是學習了一下,並寫篇部落格儲存,以便學習以及日後用到。 程式碼如下: import java.util.HashMap im

字串相似演算法(編輯距離演算法 Levenshtein Distance)

在搞驗證碼識別的時候需要比較字元程式碼的相似度用到“編輯距離演算法”,關於原理和C#實現做個記錄。 據百度百科介紹: 編輯距離,又稱Levenshtein距離(也叫做Edit Distance),是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數,如果它們的距離越大,說明它們越是不同。許可

DSSM演算法-計算文字相似

轉載請註明出處: http://blog.csdn.net/u013074302/article/details/76422551 導語 在NLP領域,語義相似度的計算一直是個難題:搜尋場景下query和Doc的語義相似度、feeds場景下Doc和Doc的語義相似度、機器翻譯場景下A句

演算法介紹(3) 編輯距離演算法-字串相似

           編輯距離,又稱Levenshtein距離,是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數。        具體的操作方法為:     

計算文字相似方法大全-簡單說

本編文章是方法論-主要給大家介紹原理思路 簡單講解 基於關鍵詞的空間向量模型的演算法,將使用者的喜好以文件描述並轉換成向量模型,對商品也是這麼處理,然後再通過計算商品文件和使用者偏好文件的餘弦相似度。 文字相似度計算在資訊檢索、資料探勘、機器翻譯、文件複製檢測等領域

應用實戰: 如何利用Spark叢集計算物品相似

本文是Spark調研筆記的最後一篇,以程式碼例項說明如何藉助Spark平臺高效地實現推薦系統CF演算法中的物品相似度計算。 在推薦系統中,最經典的推薦演算法無疑是協同過濾(Collaborative Filtering, CF),而item-cf又是CF演算法中一個實現簡單

求解字串間最短距離(字串相似)

問題描述: 給定任意兩個字串,比如:str1=“abcd”和str2=“gbcdz”,計算這兩個字串間的相似度。計算兩字串的相似度可等價於計算將str1變換到str2所需要的最少步驟。 問題分析: 為計算將str1變換到str2所需最小操作步驟,必須先對變

相似URL判定及字串相似距離

相似URL判定 edit distance缺點 基於結構來判斷URL相似度,去掉數字。字串是否也需要去掉自身只保留結構,或者保留存在長度的結構,可以根據情況來靈活取捨。 抽象一下特徵 1、站點特徵:如果兩個url站點一樣,則特徵取值1,否則取值0; 2、

Oracle字串相似查詢

Oracle字串相似度查詢 參考地址:https://www.cnblogs.com/lytwajue/p/6812556.html Oracle函式: SYS.UTL_MATCH.EDIT_DISTANCE_SIMILARITY(str,patternStr) SQL示例: SELECT e.*,S