今天在群里聊天,提及了 "编辑距离" 算法。好久不用,重新练练手,免得日后用时乱找。
1. Levenshtein Distance
该算法又称之为 "编辑距离",用于计算两个字符串的相似程度。原理很简单,就是返回将第一个字符串转换(删除、插入、替换)成第二个字符串的编辑次数。次数越少,意味着字符串相似度越高。
算法原理:Wikipedia - Levenshtein distance
Step1:
人 民 共 和 时 代
0, 0, 0, 0, 0, 0, 0
中 1, 0, 0, 0, 0, 0, 0
华 2, 0, 0, 0, 0, 0, 0
人 3, 0, 0, 0, 0, 0, 0
民 4, 0, 0, 0, 0, 0, 0
共 5, 0, 0, 0, 0, 0, 0
和 6, 0, 0, 0, 0, 0, 0
国 7, 0, 0, 0, 0, 0, 0
Step2:
人 民 共 和 时 代
0, 1, 2, 3, 4, 5, 6
中 1, 0, 0, 0, 0, 0, 0
华 2, 0, 0, 0, 0, 0, 0
人 3, 0, 0, 0, 0, 0, 0
民 4, 0, 0, 0, 0, 0, 0
共 5, 0, 0, 0, 0, 0, 0
和 6, 0, 0, 0, 0, 0, 0
国 7, 0, 0, 0, 0, 0, 0
Step3:
人 民 共 和 时 代
0, 1, 2, 3, 4, 5, 6
中 1, 1, 2, 3, 4, 5, 6
华 2, 2, 2, 3, 4, 5, 6
人 3, 2, 3, 3, 4, 5, 6
民 4, 3, 2, 3, 4, 5, 6
共 5, 4, 3, 2, 3, 4, 5
和 6, 5, 4, 3, 2, 3, 4
国 7, 6, 5, 4, 3, 3, 4
算法实现Code:
public static int LevenshteinDistance(string s1, string s2)
{
if (s1 == s2)
return 0;
else if (String.IsNullOrEmpty(s1))
return s2.Length;
else if (String.IsNullOrEmpty(s2))
return s1.Length;
var m = s1.Length + 1;
var n = s2.Length + 1;
var d = new int[m, n];
// Step1
for (var i = 0; i < m; i++) d[i, 0] = i;
// Step2
for (var j = 0; j < n; j++) d[0, j] = j;
// Step3
for (var i = 1; i < m; i++)
{
for (var j = 1; j < n; j++)
{
var cost = s1[i - 1] == s2[j - 1] ? 0 : 1;
var deletion = d[i - 1, j] + 1;
var insertion = d[i, j - 1] + 1;
var substitution = d[i - 1, j - 1] + cost;
d[i, j] = Math.Min(Math.Min(deletion, insertion), substitution);
}
}
return d[m - 1, n - 1];
}
2. LCS
LCS (Longest Common Subsequence) 算法用于找出两个字符串最长公共子串。
算法原理:
(1) 将两个字符串分别以行和列组成矩阵。
(2) 计算每个节点行列字符是否相同,如相同则为 1。
(3) 通过找出值为 1 的最长对角线即可得到最长公共子串。
人 民 共 和 时 代
中 0, 0, 0, 0, 0, 0
华 0, 0, 0, 0, 0, 0
人 1, 0, 0, 0, 0, 0
民 0, 1, 0, 0, 0, 0
共 0, 0, 1, 0, 0, 0
和 0, 0, 0, 1, 0, 0
国 0, 0, 0, 0, 0, 0
为进一步提升该算法,我们可以将字符相同节点(1)的值加上左上角(d[i-1, j-1])的值,这样即可获得最大公用子串的长度。如此一来只需以行号和最大值为条件即可截取最大子串。
人 民 共 和 时 代
中 0, 0, 0, 0, 0, 0
华 0, 0, 0, 0, 0, 0
人 1, 0, 0, 0, 0, 0
民 0, 2, 0, 0, 0, 0
共 0, 0, 3, 0, 0, 0
和 0, 0, 0, 4, 0, 0
国 0, 0, 0, 0, 0, 0
算法实现Code:
public static string LCS(string s1, string s2)
{
if (s1 == s2)
return s1;
else if (String.IsNullOrEmpty(s1) || String.IsNullOrEmpty(s2))
return null;
var d = new int[s1.Length, s2.Length];
var index = 0;
var length = 0;
for (int i = 0; i < s1.Length; i++)
{
for (int j = 0; j < s2.Length; j++)
{
// 左上角值
var n = i - 1 >= 0 && j - 1 >= 0 ? d[i - 1, j - 1] : 0;
// 当前节点值 = "1 + 左上角值" : "0"
d[i, j] = s1[i] == s2[j] ? 1 + n : 0;
// 如果是最大值,则记录该值和行号
if (d[i, j] > length)
{
length = d[i, j];
index = i;
}
}
}
return s1.Substring(index - length + 1, length);
}
分享到:
相关推荐
1. **Levenshtein距离**:也称为编辑距离,它计算的是从一个字符串转换为另一个字符串所需的最少单字符编辑(插入、删除或替换)次数。在Delphi中,你可以实现一个动态规划的算法来计算Levenshtein距离。 2. **...
9. **动态规划和字符串**:在解决一些复杂问题时,如最长公共子序列、编辑距离等,动态规划常与字符串处理结合使用。 通过这个实验,你不仅会掌握数组和字符串的基本操作,还能了解它们在实际问题中的应用。这将为...
- **基于字符串比较的方法**:将源代码转换为标记串形式,再利用字符串匹配算法(如最长公共子序列、编辑距离等)来度量相似度。 ##### 3.2 基于词频统计的方法 词频统计法是基于信息检索技术中的向量空间模型,...
### 知识点总结 #### 一、基础编程题(初级) ... 字符串编辑距离** - **知识点**: 动态规划、字符串编辑 - **实现方式**: 使用动态规划算法求解两个字符串之间的编辑距离,即最少插入和删除操作数。
7. **动态规划**:许多字符串问题可以通过动态规划策略求解,例如最长公共子序列、编辑距离等。 8. **滑动窗口**:在给定长度的窗口内处理字符串,常用于查找子串出现的最大次数、最小字典序等问题。 9. **双指针...
编辑距离则衡量的是将一个字符串转换成另一个字符串所需要的最少编辑操作次数(如插入、删除、替换字符)。 - **基于词频特征**:主要使用TF-IDF(Term Frequency-Inverse Document Frequency)方法,这是一种评估...
9. 字符串处理基本定义和算法:字符串操作是信息检索中的重要计算环节,包括字符串的编辑距离(Levenshtein距离)、精确匹配、k-近似匹配和最大公共子串的动态规划算法思想等。这些算法可以应用于文档相似度计算、...
5. 最长回文子串:要求找出字符串中的最长回文子串。 针对以上问题,动态规划可以使用“状态”和“状态转移方程”来描述问题的解决过程。状态是指某个问题的子问题的解的集合,而状态转移方程描述了状态之间的转移...
2. **编辑距离**(Levenshtein Distance):衡量两个字符串通过插入、删除或替换操作变成彼此所需的操作次数。编辑距离越小,文本相似度越高。 3. **余弦相似度**:通过计算两个文本向量的夹角余弦值来评估它们的...
- **知识点**:SQL查询中使用字符串函数提取子串。 - **解析**:在SQL查询中,`Mid()`函数用于从指定位置开始提取字符串的一部分。题目中要查找编号第3、4个字符为“03”的记录,应该使用`Mid([学生编号],3,2)="03"`...
例如,背包问题、最长公共子序列、最小编辑距离等。 6. **图算法**: - **深度优先搜索(DFS)**和**广度优先搜索(BFS)**:用于遍历或搜索图。DFS适用于寻找连通性,BFS适用于寻找最短路径。 7. **字符串操作**...