编辑距离的应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编辑距离的应用相关的知识,希望对你有一定的参考价值。

参考技术A

最小编辑距离通常作为一种相似度计算函数被用于多种实际应用中,详细如下: (特别的,对于中文自然语言处理,一般以词为基本处理单元) DNA分析:基因学的一个主要主题就是比较 DNA 序列并尝试找出两个序列的公共部分。如果两个 DNA 序列有类似的公共子序列,那么这些两个序列很可能是同源的。在比对两个序列时,不仅要考虑完全匹配的字符,还要考虑一个序列中的空格或间隙(或者,相反地,要考虑另一个序列中的插入部分)和不匹配,这两个方面都可能意味着突变(mutation)。在序列比对中,需要找到最优的比对(最优比对大致是指要将匹配的数量最大化,将空格和不匹配的数量最小化)。如果要更正式些,可以确定一个分数,为匹配的字符添加分数、为空格和不匹配的字符减去分数。 全局序列比对尝试找到两个完整的序列 S1和 S2之间的最佳比对。以下面两个 DNA 序列为例:
S1= GCCCTAGCG
S2= GCGCAATG
如果为每个匹配字符一分,一个空格扣两分,一个不匹配字符扣一分,那么下面的比对就是全局最优比对:
S1\'= GCCCTAGCG
S2\'= GCGC-AATG
连字符(-)代表空格。在 S2\'中有五个匹配字符,一个空格(或者反过来说,在 S1\'中有一个插入项),有三个不匹配字符。这样得到的分数是 (5 * 1) + (1 * -2) + (3 * -1) = 0,这是能够实现的最佳结果。
使用局部序列比对,不必对两个完整的序列进行比对,可以在每个序列中使用某些部分来获得最大得分。使用同样的序列 S1和 S2,以及同样的得分方案,可以得到以下局部最优比对 S1\'\'和 S2\'\':
S1 = GCCCTAGCG
S1\'\'= GCG
S2\'\'= GCG
S2 = GCGCAATG
这个局部比对的得分是 (3 * 1) + (0 * -2) + (0 * -1) = 3。 拼写纠错(Spell Correction):又拼写检查(Spell Checker),将每个词与词典中的词条比较,英文单词往往需要做词干提取等规范化处理,如果一个词在词典中不存在,就被认为是一个错误,然后试图提示N个最可能要输入的词——拼写建议。常用的提示单词的算法就是列出词典中与原词具有最小编辑距离的词条。 这里肯定有人有疑问:对每个不在词典中的词(假如长度为len)都与词典中的词条计算最小编辑距离,时间复杂度是不是太高了?的确,所以一般需要加一些剪枝策略,如: 因为一般拼写检查应用只需要给出Top-N的纠正建议即可(N一般取10),那么我们可以从词典中按照长度依次为len、len-1、len+1、len-2、len-3、...的词条比较; 限定拼写建议词条与当前词条的最小编辑距离不能大于某个阈值; 如果最小编辑距离为1的候选词条超过N后,终止处理; 缓存常见的拼写错误和建议,提高性能。 命名实体抽取(Named Entity Extraction):由于实体的命名往往没有规律,如品牌名,且可能存在多种变形、拼写形式,如“IBM”和“IBM Inc.”,这样导致基于词典完全匹配的命名实体识别方法召回率较低,为此,我们可以使用编辑距离由完全匹配泛化到模糊匹配,先抽取实体名候选词。 具体的,可以将候选文本串与词典中的每个实体名进行编辑距离计算,当发现文本中的某一字符串的编辑距离值小于给定阈值时,将其作为实体名候选词;获取实体名候选词后,根据所处上下文使用启发式规则或者分类的方法判定候选词是否的确为实体名。 实体共指(Entity Coreference):通过计算任意两个实体名之间的最小编辑距离判定是否存在共指关系?如“IBM”和“IBM Inc.”, "Stanford President John Hennessy "和"Stanford University President John Hennessy"。 机器翻译(Machine Translation): 识别平行网页对:由于平行网页通常有相同或类似的界面结构,因此平行网页在HTML结构上应该有很大近似度。首先将网页的HTML标签抽取出来,连接成一个字符串,然后用最小编辑距离考察两个字符串的近似度。实际中,此策略一般与文档长度比例、句对齐翻译模型等方法结合使用,以识别最终的平行网页对。 自动评测:首先存储机器翻译原文和不同质量级别的多个参考译文,评测时把自动翻译的译文对应到与其编辑距离最小的参考译文上,间接估算自动译文的质量,如下图所示: 字符串核函数(String Kernel):最小编辑距离作为字符串之间的相似度计算函数,用作核函数,集成在SVM中使用。

使用回溯法解决编辑距离问题(C语言)

回溯法

应用回溯法时,解空间往往以树的结构表示。回溯法以深度优先的方式搜索解空间树。如果回溯法在执行过程中判断解空间树的某个节点不包含问题的解时,则跳过对以该节点为根的子树的搜索,逐层向其祖先节点回溯;否则进入该子树,继续按深度优先策略搜索。
回溯法的搜索过程如下:从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。

此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。简单来讲回溯法的基本思想就是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。

编辑距离

两个字符串之间,由一个转成另一个所需的最少编辑操作次数,设A和B是两个字符串,允许的字符操作包括:
(1)添加一个字符
(2)删除一个字符
(3)修改一个字符
要用最少的字符操作将字符串A转换为字符串B。
编辑距离d(A,B)的定义是把一个字符串A通过“插入、删除和替换”这样的编辑操作编程另外一个字符串操作变成另外一个字符串(B)所需要的最少编辑次数(代价或者费用最低)。从另外一个角度来看,可以将“字符串之间的编辑距离”视为“字符串之间的相似度”(和“最长公共子序列”问题有相同的视角),也即“编辑距离”是将一个字符串转换成另外一个字符串的代价(转换的方法可能不唯一),转换的代价越高则说明两个字符串的编辑距离越大,从而其相似度越低。
操作变成另外一个字符串(B)所需要的最少编辑次数(代价或者费用最低)。从另外一个角度来看,可以将“字符串之间的编辑距离”视为“字符串之间的相似度”(和“最长公共子序列”问题有相同的视角),也即“编辑距离”是将一个字符串转换成另外一个字符串的代价(转换的方法可能不唯一),转换的代价越高则说明两个字符串的编辑距离越大,从而其相似度越低.



可以判定,字符串 SNOWY 和 SUNNY 之间的编辑距离为 3。

解:
编辑距离问题的最优子结构性质
编辑距离问题需要多个步骤处理。对字符串 A 做最少修改步骤变换到字符串 B,每个步骤都不是独立的,受前面已经确定的步骤和后面可选步骤的共同影响。设字符串 A 有 m 个字符,字符串 B 有 n 个字符。假定已经得到将 A 的 1 ~ m 个字符转换为 B 的 1 ~ n 个字符所需要的最优解,即最少编辑次数;那么其子问题“将 A 的 1 ~ i 个字符转换为 B 的 1 ~ j 个字符”也一定是最优的,否则的话(反证法),存在一个子问题的最优解,从而导致整个问题有一个更少的编辑次数,这和已知的最优解矛盾。所以编辑距离存在最优子结构性质。

建立状态方程





代码


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;


#define STR_LEN           100
#define TRUE              1
#define FALSE             0


int  FindTripleMin( int a, int b, int c );
int  CalcEditDistance( char *StrA, char *StrB, int **d );
void PrintEditDistanceMatrix( int **d, int RowNum, int ColNum );

char StrA[ STR_LEN ];
char StrB[ STR_LEN ];
int  d[STR_LEN][STR_LEN];
int pp[STR_LEN][STR_LEN];


int FindTripleMin( int a, int b, int c )

    int t = ( a < b ) ? a : b;

    return ( ( t < c ) ? t : c );



// ( 1 ) A = fxpimu  B = xwrs  d( A, B ) = 5
// ( 2 ) A = abc     B = cba   d( A, B ) = 2
// ( 3 ) A = stot    B = stop  d( A, B ) = 1
// ( 4 ) A = cd      B = abcb  d( A, B ) = 3
int CalcEditDistance()

    
    for( int i = 0; i <= strlen( StrA ); i++ )
        d[ i ][ 0 ] = i;

    for( int j = 0; j <= strlen( StrB ); j++ )
        d[ 0 ][ j ] = j;

    
    for( int i = 1; i <= strlen( StrA ); i++ )
        for( int j = 1; j <= strlen( StrB ) ; j++)
            char x = StrA[i-1];
            char y = StrB[j-1];
          
            if(x == y)
                d[i][j] =d[i-1][j-1] + 0;
            
            else
                d[i][j] = FindTripleMin(d[i][j-1]+1 , d[i-1][j] + 1 , d[i-1][j-1] + 1);
            
        
    


    return d[ strlen( StrA ) ][ strlen( StrB ) ];


int FindBack()

    int m = strlen( StrA );
    int n = strlen( StrB );

    while (n>=0 || m>=0)
       
        if (n && d[m][n-1]+1 == d[m][n])
        
            //printf("%d " ,m);
            printf("\\t插入 %c\\n" , (StrB[n-1]));
            n -= 1;
            continue;
        
        
        if (m && d[m-1][n]+1 == d[m][n])
        
            //printf("%d " ,m);
            printf("\\t删除 %c\\n" , (StrA[m-1]));
            m -= 1;
            continue;
        
        
        if (d[m-1][n-1]+1 == d[m][n])
        
            //printf("%d " ,m);
            printf("\\t替换 %c ---  %c\\n" , StrA[m-1],StrB[n-1]);
            n -= 1;
            m -= 1;
            continue;
        
        if (d[m-1][n-1] == d[m][n])
        
            n -= 1;
            m -= 1;
        
    



void PrintEditDistanceMatrix(int RowNum, int ColNum )

    int i, j;

    printf( "\\t编辑距离矩阵是 : \\n" );
    for ( i = 0; i <= RowNum - 1; i++ )
    
        printf( "\\t" );
        for ( j = 0; j <= ColNum - 1; j++ )
            printf( "%d ", d[ i ][ j ] );
        printf( "\\n" );
    
    printf( "\\n\\n" );



int main(void)


    int  i, m, n, dAB;

    system( "cls" );

    printf( "\\n\\n\\t输入字符串A  : " );
    //cin >> StrA ;
    scanf( "%s", StrA );
    m = strlen( StrA );

    printf( "\\n\\t输入字符串B: : " );
    getchar();
    //cin >> StrB ;
    scanf( "%s", StrB );
    n = strlen( StrB );


  
    dAB = CalcEditDistance();
    FindBack();
    
    cout << "\\t编辑距离: " << dAB <<endl;
    

    PrintEditDistanceMatrix(( m + 1 ), ( n + 1 ) );

    for ( i = 0; i <= m; i++ )
        free( d[ i ] );
    free( d );
    return 0;



//

以上是关于编辑距离的应用的主要内容,如果未能解决你的问题,请参考以下文章

编辑距离算法

51nod 1183 - 编辑距离 - [简单DP][编辑距离问题][Levenshtein距离问题]

java 编辑距离类问题编辑距离

最小编辑距离python

编辑距离问题

编辑距离算法(Levenshtein)