有关编辑距离计算的一点整理
(完整版)距离运算法则
(完整版)距离运算法则距离运算法则1. 引言距离运算法则是在数学和计算机科学中广泛应用的一种计算距离的方法。
通过对不同对象之间的差异进行度量,可以提供有关它们相似性或关系的定量信息。
本文将介绍距离运算法则的基本定义和常见应用。
2. 距离的定义在距离运算法则中,距离通常被定义为对象之间的差异的度量。
常见的距离度量方式包括欧几里得距离、曼哈顿距离和闵可夫斯基距离等。
这些距离度量方式在不同的领域和应用中有着不同的适用场景和计算方法。
3. 欧几里得距离(Euclidean Distance)欧几里得距离是最常见的距离度量方式之一,特别适用于连续特征的比较。
它计算两个对象间的直线距离,公式如下:d(A, B) = √((x2 - x1)^2 + (y2 - y1)^2)其中,A 和 B 是两个对象的坐标点,x1 和 y1 分别是对象 A 的坐标,x2 和 y2 分别是对象 B 的坐标。
4. 曼哈顿距离(Manhattan Distance)曼哈顿距离是另一种常见的距离度量方式,也被称为城市街区距离或 L1 距离。
它计算两个对象之间的直线距离,公式如下:d(A, B) = |x2 - x1| + |y2 - y1|其中,A 和 B 是两个对象的坐标点,x1 和 y1 分别是对象 A 的坐标,x2 和 y2 分别是对象 B 的坐标。
5. 闵可夫斯基距离(Minkowski Distance)闵可夫斯基距离是欧几里得距离和曼哈顿距离的一般化表达。
它使用一个参数 p,公式如下:d(A, B) = ((|x2 - x1|^p)^1/p + (|y2 - y1|^p)^1/p)^1/p当 p = 1 时,闵可夫斯基距离等价于曼哈顿距离;当 p = 2 时,闵可夫斯基距离等价于欧几里得距离。
6. 应用场景距离运算法则在许多领域和应用中被广泛应用。
例如,在数据挖掘中,通过计算不同样本之间的距离,可以进行聚类和分类分析。
在机器研究中,通过计算样本特征之间的距离,可以进行相似性度量和模型训练。
距离的公式高考知识点
距离的公式高考知识点距离的公式在数学中,距离是一个基本的概念,用来描述物体之间的间隔或者空间中的位置。
在解决问题时,我们经常需要计算距离。
而计算距离的核心就是掌握距离的公式。
在高考中,距离的公式也是一个重要的知识点。
本文将介绍一些常见的距离公式及其应用。
第一种常见的距离公式是直线距离的计算公式。
直线距离是两点之间的最短路径长度。
假设在平面上有两个点A(x₁, y₁)和B(x₂, y₂),那么它们之间的直线距离可以使用勾股定理来计算,即:AB = √((x₂ -x₁)² + (y₂ - y₁)²)。
这个公式可以应用于各种问题,比如计算城市之间的最短路程,或者计算两个物体之间的间隔。
第二种距离公式是三维空间中的直线距离的计算公式。
在三维空间中,我们可以用(x₁, y₁, z₁)和(x₂, y₂, z₂)表示两点的坐标。
根据勾股定理的拓展,我们可以使用三维欧氏距离公式来计算这两点之间的距离,即:AB = √((x₂ - x₁)² + (y₂ - y₁)² + (z₂ - z₁)²)。
这个公式在计算物体间的三维位移或者空间距离时非常有用。
除了直线距离公式,我们还需要掌握其他类型的距离公式。
例如,切线距离是指一条直线与一个曲线之间的距离。
假设给定一个曲线的方程为y=f(x),我们想要在点P(x₀, y₀)处找到与曲线切线相切的直线。
这条直线与曲线之间的切线距离可以使用以下公式来计算:d = |f(x₀) - y₀| / √(1 + (f'(x₀))²),其中f'(x₀)表示曲线在点P处的导数。
这个公式在计算切线距离时非常有用,可以帮助我们了解在给定一条曲线的情况下,点到曲线的最短距离。
此外,我们还有其他形式的距离公式,比如曼哈顿距离和闵可夫斯基距离。
曼哈顿距离是在网格上计算两点之间的距离时常用的距离度量方式。
它简单地定义为两点横坐标差的绝对值加上纵坐标差的绝对值,即:d = |x₂ - x₁| + |y₂ - y₁|。
c语言计算字符串编辑距离
c语言计算字符串编辑距离C语言是一种广泛应用于软件开发领域的编程语言,它具有高效、灵活和跨平台等优势。
在字符串处理的应用中,计算字符串编辑距离是一项重要的任务。
本文将介绍什么是字符串编辑距离以及如何使用C语言计算字符串编辑距离。
什么是字符串编辑距离呢?字符串编辑距离,也称为Levenshtein 距离,是衡量两个字符串之间相似度的一种度量方式。
它表示将一个字符串转换为另一个字符串所需的最少编辑操作次数。
编辑操作包括插入、删除和替换字符。
在C语言中,我们可以通过动态规划的方法来计算字符串编辑距离。
动态规划是一种解决最优化问题的算法思想,它将问题分解为若干个子问题,并通过保存子问题的最优解来求解原问题的最优解。
下面,我们来看一下如何使用C语言计算字符串编辑距离。
首先,我们定义一个二维数组dp,其中dp[i][j]表示将字符串A的前i个字符转换为字符串B的前j个字符所需的最小编辑操作次数。
然后,我们可以根据以下递推公式来计算dp数组的值:1. 当i=0时,dp[i][j] = j,表示将空字符串转换为字符串B的前j个字符所需的编辑操作次数。
2. 当j=0时,dp[i][j] = i,表示将字符串A的前i个字符转换为空字符串所需的编辑操作次数。
3. 当i>0且j>0时,如果A[i]等于B[j],则dp[i][j] = dp[i-1][j-1],表示不需要进行编辑操作;如果A[i]不等于B[j],则dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1),表示需要进行插入、删除或替换操作中的最小次数。
通过遍历字符串A和字符串B的所有字符,我们可以得到dp数组的最后一个元素dp[m][n],其中m和n分别表示字符串A和字符串B 的长度。
dp[m][n]的值即为字符串A和字符串B之间的编辑距离。
接下来,让我们通过一个示例来演示如何使用C语言计算字符串编辑距离。
编辑距离(LevenshteinDistance)
编辑距离(LevenshteinDistance)Levenshtein distance,中文名为最小编辑距离(EditDistance),其目的是找出两个字符串之间需要改动多少个字符后变成一致,如果它们的距离越大,说明它们越是不同。
许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
public static double Levenshtein(string x, string y){if(x == null || x.Length == 0){if (y == null|| y.Length == 0)return 0;return y.Length;}else{if (y == null|| y.Length == 0)return x.Length;}int[,]d = new int[x.Length+ 1, y.Length + 1];for(int i = 0; i <= x.Length; i++)d[i, 0] = i;for(int i = 0; i <= y.Length; i++)d[0, i] = i;for(int i = 0; i < x.Length; i++){for (int j = 0; j < y.Length; j++){int cost = (x[i] == y[j]) ? 0 : 1;int a = d[i, j + 1] + 1;int b = d[i + 1, j] + 1;int c = d[i, j] + cost;d[i + 1, j + 1] = Math.Min(Math.Min(a, b), c);}}return d[x.Length, y.Length];}通过微信学习的知识只能是碎片化的知识,作为新时代的我们希望能够构建自己的知识结构,使我们的知识体系化,系统化,以后在遇到碎片化的知识,我们做的只是融合到自己的知识结构中,故我们将推出“与LSGO一起学”系列课程,帮助大家来构建知识框架,初步规划有:1. “与LSGO一起学C++”;2. “与LSGO一起学C#”;3. “与LSGO一起学Matlab”;4. “与LSGO一起学数据结构”;5. “与LSGO一起学设计模式”;6. “与LSGO一起学可视化建模语言(UML)”;7. “与LSGO一起学线性代数”;8. “与LSGO一起学高等数学”9. “与LSGO一起学概率论与数理统计”;10. “与LSGO一起学抽象代数;11. “与LSGO一起学点集拓扑”12. “与LSGO一起学数字图像处理”;13. “与LSGO一起学智能计算”;如果对这些内容感兴趣,可以一起来学习讨论。
编辑距离公式
编辑距离公式
编辑距离公式是一种用于比较两个字符串相似度的算法,也被称为Levenshtein距离。
其基本思想是通过计算将一个字符串转换成另一个字符串所需的最小操作次数来衡量两个字符串之间的相似程度。
这些操作可以包括插入、删除和替换字符。
具体来说,编辑距离公式的计算方法如下:
设字符串A和B的长度分别为m和n,定义矩阵D[m+1][n+1],其中D[i][j]表示A[1...i]和B[1...j]之间的编辑距离。
初始化D[0][0]=0,D[i][0]=i,D[0][j]=j,即空串与任意一个字符串之间的编辑距离为其长度。
对于i=1...m和j=1...n,根据当前字符是否相等,分别执行下列操作:
如果A[i]=B[j],则D[i][j]=D[i-1][j-1],表示当前位置的字符已经匹配上了,编辑距离不需要变化。
否则,可执行三种操作中的一种:
1. 插入:D[i][j]=D[i][j-1]+1,表示将B[j]插入到A[i]后面。
2. 删除:D[i][j]=D[i-1][j]+1,表示将A[i]删除。
3. 替换:D[i][j]=D[i-1][j-1]+1,表示用B[j]替换A[i]。
最终,编辑距离即为D[m][n]。
编辑距离公式可用于拼写检查、语音识别、文本相似度计算等应用场景。
在实际应用中,为了提高效率,可以通过动态规划等算法对其进行优化。
编辑距离算法原理
编辑距离算法原理一、引言编辑距离算法是一种用于计算两个字符串之间的相似度的算法。
它可以衡量两个字符串之间的差异程度,即使这些字符串有不同的长度或者包含不同的字符。
在自然语言处理、信息检索、拼写纠正等领域中都有广泛应用。
二、编辑距离定义编辑距离(Edit Distance),又称Levenshtein距离,是指将一个字符串转换成另一个字符串所需的最少操作次数。
这里的操作包括插入一个字符、删除一个字符或者替换一个字符。
例如,将单词“kitten”转换成单词“sitting”需要如下三个操作:将"k"替换为"s",将"e"删除,将"n"替换为"g"。
因此,它们之间的编辑距离为3。
三、动态规划实现动态规划是解决编辑距离问题最常见和有效的方法。
我们可以定义一个二维数组dp[i][j]表示第一个字符串前i个字符和第二个字符串前j个字符之间的编辑距离。
对于dp[i][j],有以下三种情况:1. 如果第一个字符串和第二个字符串都为空,则dp[0][0]=0;2. 如果只有第一个字符串为空,则dp[0][j]=j;3. 如果只有第二个字符串为空,则dp[i][0]=i;对于其他情况,我们需要进行状态转移:1. 如果第i个字符和第j个字符相等,则dp[i][j]=dp[i-1][j-1];2. 如果第i个字符和第j个字符不相等,则dp[i][j]=min(dp[i-1][j],dp[i][j-1], dp[i-1][j-1])+1。
其中,dp[i-1][j]表示插入操作,dp[i][j-1]表示删除操作,dp[i-1][j-1]表示替换操作。
最后得到的dp[m][n]即为两个字符串之间的编辑距离。
四、优化在实际应用中,由于字符串长度可能非常大,上述动态规划算法的时间复杂度为O(mn),其中m和n分别为两个字符串的长度。
最短编辑距离算法(Minimum Edit Distance)
n = length (target) m = length (source) Create matrix d [n, m]; i=3 j=2 d[3,2] = min
d[2,2]+insert(t[3])=3 d[2,1]+substitute(s[2],t[3])=1 d[3,1]+delete(s[2])=3
=1
最小编辑距离计算示例
source : target : s o t s t o p
j
3 2 1 0 #
t o s # 0
2 1 0 s 1
1 2 1 t 2 2 o 3 p 4
i
n = length (target) m = length (source) Create matrix d [n, m]; i=3 j=1 d[3,1] = min
i
t o p (3. 插入p,1分,累计3分) t 编辑操作③ s ot stot sto stop 编辑操作④ (1. 插入t,1分,累计1分) (2. 删除t,1分,累计2分) (3. 插入p,1分,累计3分)
s o sto stop
t (1. 插入t,1分,累计1分) (3. 删除t,1分,累计3分)
d[1,2]+insert(t[2]) = 2 d[1,1]+substitute(s[2],t[2]) =2 d[2,1]+delete(s[2]) = 2
=2
最小编辑距离计算示例
source : target : s o t s t o p
j
3 2 1 0 #
t o s # 0
2 1 0 s 1
= 0 if target[i] = source[j] otherwise
编辑距离
编辑距离维基百科,自由的百科全书跳转到:导航,搜索在信息理论和计算机科学,编辑字符串的字符间的距离是需要的操作数转换成其他其中之一。
有几种不同的方法来定义一个编辑距离,并有不同的算法来计算下的定义它的价值。
见:•汉明距离•最长共同子序列问题•Levenshtein距离•达梅劳- Levenshtein距离•哈罗,温克勒距离•瓦格纳菲舍尔编辑距离•乌科宁的算法•伯格的算法[编辑]•模糊字符串搜索[编辑]外部链接•文字::WagnerFischer,一对瓦格纳菲舍尔Perl的执行编辑距离这是一个与计算机科学小作品。
你可以通过扩充其内容。
Levenshtein距离维基百科,自由的百科全书跳转到:导航,搜索这篇文章引用需要额外的验证。
请协助改善这篇文章加入可靠的参考。
条目内容可能受到挑战,并移除。
(2010年2月)在信息理论和计算机科学,Levenshtein距离是衡量两个序列(即,一个编辑的距离)不同数额的指标。
编辑距离一词经常被用来指专门Levenshtein距离。
两个字符串之间的Levenshtein距离被定义为最小数目的编辑需要一个字符串转化成其他,在允许的编辑操作被插入,删除,或单个字符替换。
它得名于弗拉基米尔莱文斯坦,谁认为这个距离在1965年[1]。
内容[隐藏]•1例•2应用•3的关系与其他编辑距离度量•4 Levenshtein距离计算Ø 4.1正确性证明Ø 4.2可能改善Ø 4.3上限和下限•5参见•6注•7外部链接[编辑]范例例如,Levenshtein距离之间的“小猫”和“会议”是3,因为以下三个转变成其他的编辑之一,是没有办法做少于三个的编辑它:1。
小猫→sitten(对'替代s'以'K的)2。
sitten→坐在(替换'我'为'电子')3。
坐在→坐(插入'克在结束')。
[编辑]应用在近似串匹配,目标是寻找短串匹配,比如,从字典,在许多较长的文本,在不同情况下的一个小数目,是可以预期的字符串。
编辑距离问题详解
编辑距离问题详解编辑距离,是指将一个字符串转换成另一个字符串所需的最小操作数。
可以定义三种操作:插入一个字符、删除一个字符、替换一个字符。
那么如何求出两个字符串的编辑距离呢?本文将详细介绍这一问题。
1. 定义状态设dp[i][j]表示将字符串A的前i个字符转换成字符串B的前j 个字符所需的最小操作次数。
2. 初始化当A或B其中一个为空字符串时,将一个空串转换成另一个字符串需要的最小操作数为另一个字符串的长度。
因此,有:dp[i][0]=i;dp[0][j]=j;3. 转移方程当A[i]等于B[j]时,dp[i][j]等于dp[i-1][j-1],不需要操作。
当A[i]不等于B[j]时,可以进行如下三种操作:(1)将A的前i-1个字符转换成B的前j个字符,然后再删除A[i],即可转换成B的前j个字符,此时操作数为dp[i-1][j]+1。
(2)在A的前i个字符后面添加一个字符,然后将A的前i个字符转换成B的前j-1个字符,即可转换成B的前j个字符,此时操作数为dp[i][j-1]+1。
(3)将A的前i-1个字符转换成B的前j-1个字符,然后将A[i]替换成B[j],即可转换成B的前j个字符,此时操作数为dp[i-1][j-1]+1。
由上述三种操作取最小值,即可得到状态转移方程:dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1);4. 求解根据转移方程,可以依次求解出所有的dp[i][j]。
最终的答案即为dp[A.length()][B.length()]。
5. 代码实现下面给出Java代码实现:public int minDistance(String word1, String word2) {int m = word1.length();int n = word2.length();int[][] dp = new int[m+1][n+1];for(int i=0; i<=m; i++){dp[i][0] = i;}for(int j=0; j<=n; j++){dp[0][j] = j;}for(int i=1; i<=m; i++){for(int j=1; j<=n; j++){if(word1.charAt(i-1) == word2.charAt(j-1)){dp[i][j] = dp[i-1][j-1];}else{dp[i][j] = Math.min(dp[i-1][j]+1,Math.min(dp[i][j-1]+1, dp[i-1][j-1]+1)); }}}return dp[m][n];}以上就是编辑距离问题的详解和Java代码实现。
[NLP]2.3编辑距离和对齐(EditDistanceandAlignment)
[NLP]2.3编辑距离和对齐(EditDistanceandAlignment)获得两个strings的距离,是⾮常有价值的事情。
你可以⽤这个进⾏单词的修正,例如你在office⾥⾯输⼊了单词graffe,然后软件帮你⾃动搜索最近的单词,类似graf,graft等等。
对于基因编辑来说,也⾮常有帮助。
我们都知道基因由AGCT序列组合⽽成,它们可以被视为⽂本,然后查找最近的基因序列。
Edit Distance 编辑距离我们可以使⽤编辑距离,表征两个strings的关系,其中『编辑』包含了如下操作:插⼊删除替换使⽤这三个操作,能够把⼀个字符变成另外⼀个,最少使⽤多少次,那么就是编辑距离。
如何获取最⼩编辑距离,其实就是⼀道leetcode困难题的事⼉:class Solution:def minDistance(self, word1: str, word2: str) -> int:# x轴是word2,y是word1,+1是初始位置dp = [[0]* (len(word2)+1) for _ in range(len(word1)+1)]# 初始空位置,如果想要成为word1,需要不停的insert操作for i in range(len(dp)):dp[i][0] = i# 同理,如果想要成为word2,也要不停的insertfor j in range(len(dp[0])):dp[0][j] = j# 从(1,1)开始迭代for i in range(1,len(dp)):for j in range(1,len(dp[i])):# 取左,上,左上的最⼩值,然后进⾏⼀个操作(+1)dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) + 1# 如果两个字符相同,那不⽤变,直接取左上的操作数if word1[i-1] == word2[j-1]:dp[i][j] =dp[i-1][j-1]return dp[-1][-1]。
编辑距离算法(Levenshtein)
编辑距离算法(Levenshtein)编辑距离定义:编辑距离,⼜称Levenshtein距离,是指两个字串之间,由⼀个转成另⼀个所需的最少编辑操作次数。
许可的编辑操作包括:将⼀个字符替换成另⼀个字符,插⼊⼀个字符,删除⼀个字符。
例如将eeba转变成abac:1. eba(删除第⼀个e)2. aba(将剩下的e替换成a)3. abac(在末尾插⼊c)所以eeba和abac的编辑距离就是3俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
:算法就是简单的线性动态规划(最长上升⼦序列就属于线性动态规划)。
设我们要将s1变成s2定义状态矩阵edit[len1][len2],len1和len2分别是要⽐较的字符串s1和字符串s2的长度+1(+1是考虑到动归中,⼀个串为空的情况)然后,定义edit[i][j]是s1中前i个字符组成的串,和s2中前j个字符组成的串的编辑距离具体思想是,对于每个i,j从0开始依次递增,对于每⼀次j++,由于前j-1个字符跟i的编辑距离已经求出,所以只⽤考虑新加进来的第j个字符即可插⼊操作:在s1的前i个字符后插⼊⼀个字符ch,使得ch等于新加⼊的s2[j]。
于是插⼊字符ch的编辑距离就是edit[i][j-1]+1删除操作:删除s1[i],以期望s1[i-1]能与s2[j]匹配(如果s1[i-1]前边的⼏个字符能与s2[j]前边的⼏个字符有较好的匹配,那么这么做就能得到更好的结果)。
另外,对于s1[i-1]之前的字符跟s2[j]匹配的情况,edit[i-1][j]中已经考虑过。
于是删除字符ch的编辑距离就是edit[i-1][j]+1替换操作:期望s1[i]与s2[j]匹配,或者将s1[i]替换成s2[j]后匹配。
于是替换操作的编辑距离就是edit[i-1][j-1]+f(i,j)。
其中,当s1[i]==s2[j]时,f(i,j)为0;反之为1于是动态规划公式如下:if i == 0 且 j == 0,edit(i, j) = 0if i == 0 且 j > 0,edit(i, j) = jif i > 0 且j == 0,edit(i, j) = iif 0 < i ≤ 1 且 0 < j ≤ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },当第⼀个字符串的第i个字符不等于第⼆个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0。
编辑距离问题
动态转移方程的推导
我们把上面 的几种情况 绘成表格:
a b c
a b a b a b a b c 1 2 b 1 1 c 1 2 a 0 1 d 2 2 c 2 2 b 2 1 b 1 0
a b c a b c a b c
c 1 2 2 c 1 2 2 b 1 1 2 b 1 1 2 b 2 1 2 a 1 2 3 a 1 2 2 c 2 2 1 a 2 2 2 c 2 2 2 c 2 2 2 d 3 3 2
注意
这里我们要明确一点,对于任意两字符串a、 b,它们的编辑距离不可能小于它们的长度 之差的绝对值。因为对于三种基本操作, 它们对字符串长度的影响为±1(插入和删 除)或0(修改)。 举一个例子:a的长度la=9,b的长度lb=15 则a、b的编辑距离m≥abs(la-lb) 即m≥6
动态转移方程的推导
若a=„ab‟,b=„bc‟,则它们的编辑距离m=2 若a=„ab‟,b=„cb‟,则它们的编辑距离m=1 若a=„ab‟,b=„ab‟,则它们的编辑距离m=0 若a=„abc‟,b=„cba‟,则它们的编辑距离m=2 若a=„abc‟,b=„cab‟,则它们的编辑距离m=2 若a=„abc‟,b=„bac‟,则它们的编辑距离m=2 若a=„abc‟,b=„bcd‟,则它们的编辑距离m=2 这有什么规律呢?
题目分析
乍一看仿佛是搜索,但仔细一想,这道题 用搜索是不可能实现的(至少我是这么认 为的)。那么我们就要采取新的策略:动 态规划。 我们知道,所有的动规问题都是可以分段 解决的,那么这道题也是如此。我们可以 把长的字符串拆解为短的字符串,一直拆 解到只剩下一个字符为止。
动态转移方程的推导
编辑距离算法
编辑距离算法2018-04-12 21:20:30编辑距离是针对⼆个字符串(例如英⽂字)的差异程度的量化量测,量测⽅式是看⾄少需要多少次的处理才能将⼀个字符串变成另⼀个字符串。
编辑距离可以⽤在⾃然语⾔处理中,例如拼写检查可以根据⼀个拼错的字和其他正确的字的编辑距离,判断哪⼀个(或哪⼏个)是⽐较可能的字。
DNA也可以视为⽤A、C、G和T组成的字符串,因此编辑距离也⽤在⽣物信息学中,判断⼆个DNA的类似程度。
Unix 下的 diff 及 patch 即是利⽤编辑距离来进⾏⽂本编辑对⽐的例⼦。
常⽤的编辑距离算法有:Levenshtein距离,在莱⽂斯坦距离中,可以删除、加⼊、取代字符串中的任何⼀个字元,也是较常⽤的编辑距离定义,常常提到编辑距离时,指的就是莱⽂斯坦距离。
LCS(最长公共⼦序列)距离,只允许删除、加⼊字元。
⼀、最长公共⼦序列 LCS最长公共⼦序列问题是很经典的动态规划问题,问题描述如下:LCS是Longest Common Subsequence的缩写,即最长公共⼦序列。
⼀个序列,如果是两个或多个已知序列的⼦序列,且是所有⼦序列中最长的,则为最长公共⼦序列。
⼦序列:⼀个序列A = a1,a2,……an,中任意删除若⼲项,剩余的序列叫做A的⼀个⼦序列。
也可以认为是从序列A按原顺序保留任意若⼲项得到的序列。
例如:对序列 1,3,5,4,2,6,8,7来说,序列3,4,8,7 是它的⼀个⼦序列。
对于⼀个长度为n的序列,它⼀共有2^n 个⼦序列,有(2^n –1)个⾮空⼦序列。
请注意:⼦序列不是⼦集,它和原始序列的元素顺序是相关的。
时间复杂度:对于⼀般性的LCS问题(即任意数量的序列)是属于NP-hard。
但当序列的数量确定时,问题可以使⽤动态规划(Dynamic Programming)在多项式时间内解决。
public int LCS(String s1, String s2) {if (s1.length() == 0 || s2.length() == 0) return 0;int len1 = s1.length();int len2 = s2.length();int[][] dp = new int[len1 + 1][len2 + 1];for (int i = 0; i <= len2; i++) dp[0][i] = 0;for (int i = 0; i <= len1; i++) dp[i][0] = 0;for (int i = 1; i <= len1; i++) {for (int j = 1; j <= len2; j++) {int same = s1.charAt(i - 1) == s2.charAt(j - 1) ? 1 : 0;dp[i][j] = Math.max(Math.max(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1] + same);}}return dp[len1][len2];}⼆、莱⽂斯坦距离 LevenshteinDistcance莱⽂斯坦距离,⼜称Levenshtein距离,是编辑距离的⼀种。
编辑距离算法
编辑距离算法
编辑距离(Edit Distance)是指两个字符串之间,由一个转成另一个所需的最少编辑操作次数。
许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如,将kitten转换成sitting,可以先将kitten中的k替换为s,然后在后面插入一个字符i,所以这两个字符串的编辑距离为2.
编辑距离算法通常使用动态规划的方法来求解,它会把原问题分解成多个子问题,然后逐步求解,最终得出最优解。
具体步骤如下:
1)确定矩阵大小:把字符串作为行和列,建立一个二维矩阵,矩阵大小为(n+1)*(m+1),n和m分别为字符串的长度;
2)填充矩阵:把第一行和第一列的元素,从0开始递增到n和m;
3)计算距离:从第二行第二列开始遍历矩阵,确定当前位置的值,根据如下公式:
当字符串1第i个字符与字符串2中第j个字符相等时,d[i][j] = d[i-1][j-1] 不相等时,d[i][j] = min(d[i-1][j], d[i][j-1], d[i-1][j-1]) + 1
4)返回结果:最后返回矩阵右下角的值即为最终结果。
LevenshteinDistance算法(编辑距离算法)
LevenshteinDistance算法(编辑距离算法)编辑距离编辑距离(Edit Distance),⼜称Levenshtein距离,是指两个字串之间,由⼀个转成另⼀个所需的最少编辑操作次数。
许可的编辑操作包括将⼀个字符替换成另⼀个字符,插⼊⼀个字符,删除⼀个字符。
⼀般来说,编辑距离越⼩,两个串的相似度越⼤。
例如将kitten⼀字转成sitting:sitten (k→s)sittin (e→i)sitting (→g)俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
应⽤最⼩编辑距离通常作为⼀种相似度计算函数被⽤于多种实际应⽤中,详细如下:(特别的,对于中⽂⾃然语⾔处理,⼀般以词为基本处理单元)DNA分析:基因学的⼀个主要主题就是⽐较 DNA 序列并尝试找出两个序列的公共部分。
如果两个 DNA 序列有类似的公共⼦序列,那么这些两个序列很可能是同源的。
在⽐对两个序列时,不仅要考虑完全匹配的字符,还要考虑⼀个序列中的空格或间隙(或者,相反地,要考虑另⼀个序列中的插⼊部分)和不匹配,这两个⽅⾯都可能意味着突变(mutation)。
在序列⽐对中,需要找到最优的⽐对(最优⽐对⼤致是指要将匹配的数量最⼤化,将空格和不匹配的数量最⼩化)。
如果要更正式些,可以确定⼀个分数,为匹配的字符添加分数、为空格和不匹配的字符减去分数。
全局序列⽐对尝试找到两个完整的序列 S1和 S2之间的最佳⽐对。
以下⾯两个 DNA 序列为例:S1= GCCCTAGCGS2= GCGCAATG如果为每个匹配字符⼀分,⼀个空格扣两分,⼀个不匹配字符扣⼀分,那么下⾯的⽐对就是全局最优⽐对:S1'= GCCCTAGCGS2'= GCGC-AATG连字符(-)代表空格。
在 S2'中有五个匹配字符,⼀个空格(或者反过来说,在 S1'中有⼀个插⼊项),有三个不匹配字符。
这样得到的分数是 (5 * 1) + (1 * -2) + (3 * -1) = 0,这是能够实现的最佳结果。
编辑距离算法的原理及应用
编辑距离算法,也被称为Levenshtein距离算法,是一种用于衡量两个字符串之间相似度的方法。
它通过计算将一个字符串转换为另一个字符串所需的最少操作次数来衡量它们的相似程度。
这些操作包括插入、删除和替换字符。
编辑距离算法的原理可以通过动态规划来实现。
我们可以建立一个二维的矩阵来表示两个字符串的编辑距离。
矩阵的行表示一个字符串的每个字符,列表示另一个字符串的每个字符。
矩阵中的每个元素记录了从一个字符串的某个字符到另一个字符串的某个字符所需的最少操作次数。
下面我们以字符串”march”和”cart”为例来演示编辑距离算法的计算过程:| | c | a | r | t || 0 | 1 | 2 | 3 | 4 |m | 1 | | | | |a | 2 | | | | |r | 3 | | | | |c | 4 | | | | |h | 5 | | | | |我们可以将第一行和第一列的初始值设为从空字符串转换到对应字符串所需的操作次数:| | c | a | r | t || 0 | 1 | 2 | 3 | 4 |m | 1 | 1 | 2 | 3 | 4 |a | 2 | | | | |r | 3 | | | | |c | 4 | | | | |h | 5 | | | | |我们可以根据以下递推公式计算矩阵中其他位置的值:if s1[i] == s2[j]:dp[i][j] = dp[i-1][j-1]else:dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1其中,dp[i][j]表示矩阵中第i行第j列位置的值,s1和s2分别表示两个字符串。
按照上述公式计算,我们可以得到完整的编辑距离矩阵:| | c | a | r | t || 0 | 1 | 2 | 3 | 4 |m | 1 | 1 | 2 | 3 | 4 |a | 2 | 2 | 1 | 2 | 3 |r | 3 | 3 | 2 | 1 | 2 |c | 4 | 3 | 3 | 2 | 3 |h | 5 | 4 | 4 | 3 | 3 |我们可以通过读取矩阵的右下角元素,即dp[m][n],来得到两个字符串的编辑距离。
编辑距离算法
//
// 打印矩阵
//
matrix_print(matrix, row, col);
//
// 矩阵最后的格子就是“编辑距离”
//
dis = matrix[(row*col - 1];
printf("distance = %d\n", dis);
//
// 小应用。使用“编辑距离” 来算2个串的相似度。
#include "stdio.h"
#include "malloc.h"
#include "string.h"
#define MAX(a,b) ((a)>(b)?(a):(b))
void matrix_print(char *matrix, int row, int col)
{
int i, j;
for(i=0; i<row; i++)
{
int *pCell;
pCell = GetCellPointer (pOrigin, col, row, nCols);
*pCell = x;
}
//*****************************
// Compute Levenshtein distance
//*****************************
{
int mi;
mi = a;
if (b < mi) {
mi = b;
}
if (c < mi) {
mi = c;
}
return mi;
}
//**************************************************
编辑距离(C++)
编辑距离(C++)给定两个字符串s1和s2,计算出将s1转换成s2所⽤的最少操作数。
可以对⼀个字符串进⾏如下三种操作:1.插⼊⼀个字符;2.删除⼀个字符;3.替换⼀个字符。
递归法的解题⽅式:两个字符串从后(i=s1.length()-1,j=s2.length()-1)往前⽐较,递归三要素之⼀——终⽌条件base case:i=-1或j=-1结束;递归三要素之⼆——终⽌时的处理:返回另⼀个字符剩下的长度。
即base case是i⾛完s1或j⾛完s2,可以直接返回另⼀个字符串剩下的长度,这是因为当i ⾛完s1,j没⾛完s2时,⽤插⼊操作把s2剩下的字符插⼊s1,需要j+1步(因为j从0开始);⽽当j⾛完s2⽽i没⾛完s1时,⽤删除操作把s1前⾯没处理的字符删掉,需要i+1步(因为j从0开始)。
递归要素之三————提取重复逻辑。
当⽐较的两个字符相同时,两字符串都向前搜索;⽽两个字符不同时,判断插⼊、删除、替换后哪个步骤最少,就从选那条路径。
不能理解的读者可以看以前的⼀篇博⽂。
插⼊、删除、替换是怎么操作的可以看下列代码及注释。
int dp(string s1, string s2, int i, int j){//i⾛完s1,j没⾛完s2,⽤插⼊操作把s2剩下的字符插⼊s1,需要j+1步(因为j从0开始)if (i == -1)return j + 1;//j⾛完s2⽽i没⾛完s1,⽤删除操作把s1前⾯没处理的字符删掉,需要i+1步(因为j从0开始)if (j == -1)return i + 1;//两个字符相同,直接往前移动i,j即可if (s1[i] == s2[j])return dp(s1, s2, i - 1, j - 1);else//插⼊:i不往前移,j往前移,说明只处理了s2,这是往s1中插⼊⼀个字符导致的。
处理步骤+1。
//删除:i往前移,j不往前移,说明s1处理了⼀个字符⽽s2没处理,这是s1中删除了⼀个字符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一直让我困惑的问题是:abc与ca之间的编辑距离究竟等于几?
问了很多同学和网友:大家的普遍观点是:如果在编辑距离定义中指明相邻交换操作为原子操作,那么应该等于2;反之,如果在编辑距离定义中为定义相邻交换操作为原子操作那么应该等于3。
为了更好地阐明这个问题,先给出编辑距离的两种定义形式
1.Levenshtein distance(以下简称L氏距离)。
此距离由Levenshtein 于1965年定义,在这个定义体系中有三种原子操作:
insertion,deletion,substitution(出处见论文《BINARY CODES CAPABLE OF CORRECTING,DELETIONS,INSERTIONS AND REVERSALS》);2.Damerau,F,J distance(以下简称D氏距离)。
此距离有Damerau于1964年定义,在这个定义体系中有四种原子操作:insertion,deletion,substitution,以及transpositionof ajacent symbols(出处见论文《A Technique for Computer Detection and Correction of Spelling Errors》);
两种定义的区别:
1.L氏距离的原子操作集中不包括相邻交换这个操作;
2.根据wiki上介绍:L氏距离可以处理多重编辑错误,而D式距离只能处理单一的编辑错误。
综上:
如果利用L氏编辑距离计算abc与ca之间的编辑距离,结果应该是3(删除
b->原字符串开头的a被替换为c->原字符串结尾的c被替换为a),这个是没有任何异议的;如果根据D氏距离计算abc与ca之间的编辑距离应该为2(删除b->原字符串首尾的字符a与c交换位置),现在问题就出来了:很多书籍和论文(例如Kemal Oflazor 的《Error-tolerant Finite-state Recognition with Application to Morphological Analysis and Spelling Correction》,M.W.Du and S.C.Chang的《A model and a fast algorithm for multiple errors spelliing correction》)中采用了D氏编辑距离的定义,然后又紧接着给出了如下的计算公式:
公式1:以上两篇论文中提供的编辑距离计算公式。
根据此计算公式得到的计算结果也是3。
这个时候很多会说,因为得出2的结果的时候,先删除中间的b,没有满足“顺序操作”所以得到错误的结果。
对于字符串abc的正确处理顺序应该是先处理a,然后处理b,然后处理c。
正确的计算应该是:删除a->b换成c->c换成a。
但是编辑距离应该是满足对称性的。
也就是说abc与ca的编辑距离等于ca与abc 的编辑距离。
ca变成abc可以经过如下步骤:ca->ac,ac中间插入b。
因此这种说法是不太合理的,况且编辑距离的定义只是对现实情况的一种数学抽象,不考虑程序设计问题,和“顺序流”之间没有多大关系。
这个问题困扰了我很长时间,今天通过查wiki才知道了事情的来龙去脉:大体情况是这样的,L和D自己对编辑距离的定义是没有问题的,符合泛函理论中对距离定义的三个要素条件。
后来一些人就想将L和D的距离定义融合在一起,成为了Damerau–Levenshtein distance(以下简称D-L距离),认为这样就既可以克服了D定义只能识别单一编辑操作引起的错误的局限,又弥补了L 定义不包含相邻字符互换操作的遗憾。
其实上面的公式1计算的就是D-L距离。
但是这个D-L距离并不满足泛函理论中所要求的距离定义的三要素标准,它不满足三角不等式,所以这个定义是有问题的,数学上具有不严谨性。
于是也就有了将abc与ca的编辑距离错算为3的情况。
但是由于这个错误并不影响工程中的应用,并且这个公式能够给实际工作带来便利,就一直沿用了下来。
下面引用wiki上的相关段落:
Let us calculate pair-wise distances between the
strings TO, OT and OST using this algorithm. The distance between TO and OT is 1. The same for OT vs. OST. But the distance between TO and OST is 3, even though the strings can be made equal using one deletion and one transposition. Clearly, the algorithm does not compute precisely the value we want. Furthermore,
the triangle inequality does not hold.
In reality this algorithm calculates the cost of the so-called optimal string alignment, which does not always equal the edit distance.
参考资料:
/wiki/Damerau–Levenshtein_distance。