Levenshtein distance

Levenshtein distance

The Levenshtein distance is a metric for measuring the amount of difference between two sequences (i.e. an edit distance). The term edit distance is often used to refer specifically to Levenshtein distance.

The Levenshtein distance between two strings is defined as the minimum number of edits needed to transform one string into the other, with the allowable edit operations being insertion, deletion, or substitution of a single character. It is named afterVladimir Levenshtein, who considered this distance in 1965.[1]

Example

For example, the Levenshtein distance between "kitten" and "sitting" is 3, since the following three edits change one into the other, and there is no way to do it with fewer than three edits:

  1. kitten → sitten (substitution of 's' for 'k')
  2. sitten → sittin (substitution of 'i' for 'e')
  3. sittin → sitting (insertion of 'g' at the end).

Computing Levenshtein distance

Computing the Levenshtein distance is based on the observation that if we reserve amatrix to hold the Levenshtein distances between all prefixes of the first string and all prefixes of the second, then we can compute the values in the matrix byflood filling the matrix, and thus find the distance between the two full strings as the last value computed.

This algorithm, an example of bottom-up dynamic programming, is discussed, with variants, in the 1974 article TheString-to-string correction problem by Robert A. Wagner and Michael J. Fischer.

A straightforward implementation, as pseudocode for a function LevenshteinDistance that takes two strings,s of length m, and t of length n, and returns the Levenshtein distance between them:

int LevenshteinDistance(char s[1..m], char t[1..n])
{
  // for all i and j, d[i,j] will hold the Levenshtein distance between
  // the first i characters of s and the first j characters of t;
  // note that d has (m+1)x(n+1) values
  declare int d[0..m, 0..n]

  for i from 0 to m
    d[i, 0] := i // the distance of any first string to an empty second string
  for j from 0 to n
    d[0, j] := j // the distance of any second string to an empty first string

  for j from 1 to n
  {
    for i from 1 to m
    {
      if s[i] = t[j] then  
        d[i, j] := d[i-1, j-1]       // no operation required
      else
        d[i, j] := minimum
                   (
                     d[i-1, j] + 1,  // a deletion
                     d[i, j-1] + 1,  // an insertion
                     d[i-1, j-1] + 1 // a substitution
                   )
    }
  }

  return d[m,n]
}

Two examples of the resulting matrix (hovering over a number reveals the operation performed to get that number):



The invariant maintained throughout the algorithm is that we can transform the initial segments[1..i] into t[1..j] using a minimum of d[i,j] operations. At the end, the bottom-right element of the array contains the answer.

Proof of correctness

As mentioned earlier, the invariant is that we can transform the initial segment s[1..i] intot[1..j] using a minimum of d[i,j] operations. This invariant holds since:

  • It is initially true on row and column 0 because s[1..i] can be transformed into the empty stringt[1..0] by simply dropping all i characters. Similarly, we can transforms[1..0] to t[1..j] by simply adding all j characters.
  • If s[i] = t[j], and we can transform s[1..i-1] to t[1..j-1] in k operations, then we can do the same to s[1..i] and just leave the last character alone, givingk operations.
  • Otherwise, the distance is the minimum of the three possible ways to do the transformation:
    • If we can transform s[1..i] to t[1..j-1] in k operations, then we can simply addt[j] afterwards to get t[1..j] in k+1 operations (insertion).
    • If we can transform s[1..i-1] to t[1..j] in k operations, then we can removes[i] and then do the same transformation, for a total of k+1 operations (deletion).
    • If we can transform s[1..i-1] to t[1..j-1] in k operations, then we can do the same to s[1..i], and exchange the originals[i] for t[j] afterwards, for a total of k+1 operations (substitution).
  • The operations required to transform s[1..n] into t[1..m] is of course the number required to transform all ofs into all of t, and so d[n,m] holds our result.

This proof fails to validate that the number placed in d[i,j] is in fact minimal; this is more difficult to show, and involves anargument by contradiction in which we assume d[i,j] is smaller than the minimum of the three, and use this to show one of the three is not minimal.


#include <iostream>
#include <vector>
#include <string>
using namespace std;

//算法
int ldistance(const string source,const string target)
{
	//step 1
	int n = source.length();
	int m = target.length();
	if (m == 0) return n;
	if (n == 0) return m;
	//Construct a matrix
	typedef vector< vector<int> >  Tmatrix;
	Tmatrix matrix(n+1);
	for(int i=0; i<=n; i++)  matrix[i].resize(m+1);

	//step 2 Initialize

	for(int i=1;i<=n;i++) matrix[i][0]=i;
	for(int i=1;i<=m;i++) matrix[0][i]=i;

	//step 3
	for(int i=1;i<=n;i++)
	{		
		//step 4
		for(int j=1;j<=m;j++)
		{			
			//step 5			
			if(source[i-1] == target[j-1]){				
				matrix[i][j] = matrix[i-1][j-1];
			}
			else{				
				matrix[i][j] = min(matrix[i-1][j]+1,min(matrix[i][j-1]+1,matrix[i-1][j-1]+1));
			}
		}
	}//step7
	return matrix[n][m];
}

int main(){
	string s;
	string d;
	while (1)
	{
		cout<<"first string =";
		cin>>s;
		cout<<"second string =";
		cin>>d;
		int dist=ldistance(s,d);
		cout<<"dist="<<dist<<endl;
	}	
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值