字符串的编辑距离

来源:互联网 发布:淘宝怎么删除追加评论 编辑:程序博客网 时间:2024/05/01 13:23

编辑距离

编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。度娘

动态规划解法

S1 的字符串长 n1S2的字符串长 n2,用 S(i) 来表示字符串中的 i 个字符。dis[n1,n2] 表示 S1 的前 i个字符串的子串与 S2 的前 j 个字符构成的子串之间的编辑距离

对于S1S2 有一个是空串,另一个的 dis[i,0]=i 或者 dis[0j]=j

dis[i,j]=d[i1,j1]mindis[i,j1]+1,dis[i,j]+1,dis[i1,j]+1,S1(i)=S2(j)S1(i)S2(j)=dis[i,j]

(欲哭无泪。。。。\left 必须成对出现。。。真是大BUG)

算法步骤:
编辑距离的动态规划算法

(哎。。。CSDN 的Markdown 真是无力吐槽。。。)

来来来 上代码 申请的空间记得释放

#include <iostream>using namespace std;int editableDistance(string strFrom,string strDest);void initialArray2D(int** arrayTemp,int m,int n);void free2DArray(int** arrayTemp,int m,int n);void displayArray2D(int** arrayTemp,int m,int n);int minNumber(int num1,int num2,int num3);int main(){    string strOne="I LOVE READING";    string strTwo="I LOVE EATING";    cout<<"Please Enter Two Strings:\n";    //cin>>strOne>>strTwo;    int result = editableDistance(strOne,strTwo);    cout<<"\nThe distance between "<<strOne<<" and "<<strTwo<<"is "<<result<<endl;    return 0;}int editableDistance(string strFrom,string strDest){    int lenFrom = strFrom.length();    int lenDest = strDest.length();    int distace = 0;    //声明并初始化二维数组    int** arrayDis = new int*[lenFrom+1];//2D array    for(int i=0;i<=lenFrom;++i){        arrayDis[i]= new int[lenDest+1];    }    initialArray2D(arrayDis,lenFrom,lenDest);    //初始化距离数组    for(int j=1;j<=lenDest;++j){   //dis[0,j]<-j        arrayDis[0][j]=j;    }    for(int i=1; i<=lenFrom; ++i)    {        arrayDis[i][0]=i;//dis[i,0]<-i        for(int j=1; j<=lenDest; ++j)        {            if(strFrom[i-1]==strDest[j-1]){                arrayDis[i][j]=arrayDis[i-1][j-1];            }else{                arrayDis[i][j]=minNumber(arrayDis[i-1][j],arrayDis[i-1][j-1],arrayDis[i][j-1])+1;            }        }    }    //输出距离矩阵    displayArray2D(arrayDis,lenFrom,lenDest);    distace = arrayDis[lenFrom-1][lenDest-1];    free2DArray(arrayDis,lenFrom,lenDest);    return distace;}//初始化二维数组void initialArray2D(int** arrayTemp,int m,int n){    for(int i=0;i<=m;++i){        for(int j=0;j<=n;++j){            arrayTemp[i][j]=0;            //cout<<arrayTemp[i][j];        }    }}//动态数组的删除操作void free2DArray(int** arrayTemp,int m,int n){    for(int i=m;i>=0;--i){        delete[] arrayTemp[i];        arrayTemp[i] = NULL;    }    arrayTemp=NULL;}//输出二维数组void displayArray2D(int** arrayTemp,int m,int n){     for(int i=0;i<=m;++i){            cout<<endl;        for(int j=0;j<=n;++j){            cout<<arrayTemp[i][j]<<"\t";        }    }}//求三个数的最大值int minNumber(int num1,int num2,int num3){    return min(min(num1,num2),num3);}

结果图

此外,对于每次进行第 i 行的判断。。。其前面 i1 行的信息已经没有用了,因此可以将动态二维数组减少为两个数组,分别来标记当前行和前一行的值。

废话不说上代码。。。

#include <iostream>using namespace std;int editableDistance(string strFrom,string strDest);int minNumber(int num1,int num2,int num3);int main(){    string strOne="TJU";    string strTwo="NKU";    cout<<"Please Enter Two Strings:\n";    //cin>>strOne>>strTwo;    int result = editableDistance(strOne,strTwo);    cout<<"\nThe distance between "<<strOne<<" and "<<strTwo<<"is "<<result<<endl;    return 0;}int editableDistance(string strFrom,string strDest){    int lenFrom = strFrom.length();    int lenDest = strDest.length();    int arrayLen = max(lenFrom,lenDest);    int distance = 0;//记录距离    //声明并初始化二维数组    int* arrayOld = new int[arrayLen+1];    int* arrayNew = new int[arrayLen+1];    int* tempPointer = NULL;    //初始化距离数组    for(int j=0;j<=lenDest;++j){   //d[0,j]<-j        arrayOld[j]=j;    }    for(int i=1; i<=lenFrom; ++i)    {        arrayNew[0]=i;//d[i,0]<-i        for(int j=1; j<=lenDest; ++j)        {            if(strFrom[i-1]==strDest[j-1]){                arrayNew[j]=arrayOld[j-1];            }else{                arrayNew[j]=minNumber(arrayNew[j-1],arrayOld[j-1],arrayOld[j])+1;            }        }        //交换        tempPointer=arrayOld;        arrayOld = arrayNew;        arrayNew = tempPointer;    }    distance = arrayOld[arrayLen];    delete[] arrayNew;arrayNew=NULL;    delete[] arrayOld;arrayOld=NULL;    tempPointer = NULL;    return distance;//因为与arrayNew交换了,所以old是最新的结果}//求三个数的最大值int minNumber(int num1,int num2,int num3){    return min(min(num1,num2),num3);}

两个数组的结果

哎。。。友情赠送算法伪代码的 LATEX源代码。。。不要太感动。。。吼吼吼

\documentclass[11pt]{article}\usepackage{CJK}\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry}\usepackage{algorithm}\usepackage{algorithmicx}\usepackage{algpseudocode}\usepackage{amsmath}\begin{CJK*}{UTF8}{gkai}    \begin{algorithm}        \caption{编辑距离的动态规划算法}        \begin{algorithmic}[1] %每行显示行号           \For{$j \in \{1,2,...,n_2\}$} \do\\        \State  $dis[0,j] \gets j$        \EndFor        \For{$i \in \{1,2,...,n_1\}$} \do\\        \State  $dis[i,0] \gets i$             \For{$j \in \{1,2,...,n_2\}$} \do\\                \If{$S_1(i) == S_2(j) then$ }                 \State $dis[i,j] \gets dis[i-1,j-1]$                \Else                \State $dis[i,j] \gets min \{dis[i,j-1],dis[i-1,j],dis[i-1,j-1]\}+1$                \EndIf             \EndFor        \EndFor                     \end{algorithmic}    \end{algorithm}\end{CJK*}\end{document}

阅读书目

  1. 刁瑞, 谢妍. 算法笔记[M]. 电子工业出版社, 2016.
0 0
原创粉丝点击