序列和集合算法之序列比较

将一个序列变成另一个序列的最少修改步数。

例如下图,将字符串A变成字符串B,所需要的步骤为6个步骤,match表示0步,其他操作表示1步:

设计算法如下:


    public sealed class MinimumEditDistance
{
public int[,] CalculateDistance(string originalStr, String targetStr)
{
int LenA = originalStr.Length;
int LenB = targetStr.Length;
int[,] C = new int[LenA + 1, LenB + 1];
for (int i = 0; i <= LenA; C[i, 0] = i, i++) ;//targetStr为空串时的边界条件
for (int j = 0; j <= LenB; C[0, j] = j, j++) ;//originalStr为空串时的边界条件
for (int i = 1; i <= LenA; i++)
{
for (int j = 1; j <= LenB; j++)
{
//删除:考虑C[i-1,j],即i-1时已经达到最好情况,新添加的第i个字符需要删除掉
int candidateDel = C[i - 1, j] + 1;
//插入:考虑C[i,j-1],即已经在i的情况下能够达到j-1时的最好情况,此时如果考虑j的情况就是直接插入第j个字符
int candidateIns = C[i, j - 1] + 1;
//匹配:考虑C[i-1,j-1],即在i-1,j-1的情况下已经得到最好值,并且新近考虑的i和j字符相同,则无需任何额外动作
// int candidate = C[i-1, j-1];
//替换:考虑C[i-1,j-1],即在i-1,j-1的情况下已经得到最好值,并且新近考虑的i和j字符不相同,则需一次替换额外动作
//int candidate = C[i - 1, j - 1]+1;
int candidateMatRep;
if (char.Equals(originalStr[i - 1], targetStr[j - 1]))
{
candidateMatRep = C[i - 1, j - 1];
}
else
{
candidateMatRep = C[i - 1, j - 1] + 1;
}
//三者取最小代价
C[i, j] = Math.Min(Math.Min(candidateDel, candidateIns), candidateMatRep);
}
}
return C;
}
public List<OperationOnOriginalStr> GetPossibleDesicion(int[,] C, int row, int col)
{
List<OperationOnOriginalStr> lo = new List<OperationOnOriginalStr>();

for (int i = row, j = col; i > 0 || j > 0; )
{
if (C[i, j] == C[i - 1, j] + 1)//删除
{
lo.Add(new OperationOnOriginalStr(Operation.Delete, i-1));
i--;
}
else if (C[i, j] == C[i, j - 1] + 1) //插入
{
lo.Add(new OperationOnOriginalStr(Operation.Insert, i-1, j-1));
j--;
}
else if (C[i, j] == C[i - 1, j - 1])//匹配
{
lo.Add(new OperationOnOriginalStr(Operation.Match, i-1,j-1));
i--;
j--;
}
else //替换
{
lo.Add(new OperationOnOriginalStr(Operation.Replace, i-1, j-1));
i--;
j--;
}
}

return lo.Reverse<OperationOnOriginalStr>().ToList<OperationOnOriginalStr>();
}
}
public enum Operation
{
Delete,
Insert,
Replace,
Match
}
public class OperationOnOriginalStr
{
public OperationOnOriginalStr(Operation op, int aindex, int? bindex = null)
{
operation = op;
AIndex = aindex;
BIndex = bindex;
}
public Operation operation { get; set; }
public int AIndex { get; set; }
public int? BIndex { get; set; }
}

调用方法如下:

            MinimumEditDistance med = new MinimumEditDistance();
var C = med.CalculateDistance(A, B);
var steps = med.GetPossibleDesicion(C, A.Length, B.Length);
steps.ForEach(s => Console.WriteLine("Operation:{0},A[{1}],B[{2}]", s.operation, s.AIndex, s.BIndex));

作者:Andy Zeng

欢迎任何形式的转载,但请务必注明出处。

http://www.cnblogs.com/andyzeng/p/3736012.html

序列和集合算法之序列比较,布布扣,bubuko.com

时间: 2024-10-20 07:53:21

序列和集合算法之序列比较的相关文章

序列最小最优化算法(SMO)-SVM的求解(续)

在前一篇文章中,我们给出了感知器和逻辑回归的求解,还将SVM算法的求解推导到了最后一步,在这篇文章里面,我们将给出最后一步的求解.也就是我们接下来要介绍的序列最小最优化算法. 序列最小最优化算法(SMO): 首先回顾一下.我们使用广义拉格朗日函数,将目标函数和限制条件写到一起,然后证明了原始问题能够转化成对偶问题来求解.并且使用KKT条件将对偶问题化简,得到下面的问题(以非线性可分SVM的研究问题作为例子,求解): $\max \limits_{a} \ -\frac{1}{2}\sum_{i=

Python序列结构--集合

集合:元素之间不允许重复 集合属于Python无序可变序列,元素之间不允许重复 集合对象的创建与删除 直接将值赋值给变量即可创建一个集合 >>> a = {3,5}>>> type(a)<class 'set'> set()函数将列表.元组.字符串.range对象等其他可迭代对象转换为集合,如果原来的数据中存在重复元素,则转换为集合的时候只保留一个:如果原序列或迭代对象中有不可哈希的值,无法转换为集合,抛出异常 >>> a_set=set(

将排序序列的集合合并成一个排序序列

您有一个排序序列的集合,并且想要遍历所有合并在一起的排序序列. 先看如下示例,了解实际需求: >>> import heapq >>> a = [1, 4, 7, 10] >>> b = [2, 5, 6, 11] >>> for c in heapq.merge(a, b): print(c) ... 1 2 4 5 6 7 10 11 值得注意的是,heapq.merge要求所有的输入序列已排序.特别是,它不会首先将所有数据读入堆

zjnu(1183)——括号序列【基础算法?动态规划】——高级

首先,我只想声明一点,这道题有毒...我用char读入就错了,然而换成string读入就对了或者可以把定义char的数组开的大一点,原先1A的一题硬是纠结了老半天. 传送门:zjnu 题意: 就是对于一个组成的序列,添加尽量少的括号得到一个规则序列,并且输出这个序列的长度. 不过我学到了两种定义dp状态的方法: 1)定义dp[i][j]为i~j中需要添加的最少的括号数.这里我们记录s为一段字符的开始位置,e为一段字符的结束位置. ①当(a[s]=='('&&a[e]==')')||(a[s

stl集合算法

accumulate() 累加 ? accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值. ? #include<numeric> vector<int> vecIntA; vecIntA.push_back(1); vecIntA.push_back(3); vecIntA.push_back(5); vecIntA.push_back(7); vecIntA.push_back(9); int iSum = accumulate(vecIntA

C++ 根据前序遍历序列和中序遍历序列可以构造唯一的二叉树

文章转载自http://blog.csdn.net/touzani/article/details/1637195 根据前序遍历序列和中序遍历序列可以构造唯一的二叉树. 假设序列为string型 根据前序遍历的特点, 知前序序列(Pre)的首个元素(Pre[0])为根(root), 然后在中序序列(In)中查找此根(Pre[0]), 根据中序遍历特点, 知在查找到的根(root) 前边的序列为左子树, 后边的序列为右子树. 设根前边有left个元素.. 则又有, 在前序序列中, 紧跟着根(roo

求两个有序序列合并成新有序序列的中位数,求第k小数

此算法涉及一个重要数学结论:如果A[k/2-1]<B[k/2-1],那么A[0]~A[k/2-1]一定在第k小的数的序列当中,可以用反证法证明. 更加一般的结论是:k=pa+pb,如果A[pa-1]<B[pb-1],那么A[0]~A[pa-1]一定在第k小的数的序列当中. 算法思想如下: 1,假设A长度为m,B长度为n,m>n,反之亦然. 2,拆分k=pa+pb. 3,如果A[pa-1]<b[pb-1],那证明第A[0]~A[pa-1]一定在合并后k小数序列中.所以,可以把A的前面

集合框架之链表集合算法

链表集合算法: 1.链=引用 2.链表集合与数组集合的区别:在增值方面,数组集合的速度比链表集合算法[学Java,到凯哥学堂kaige123.com]的速度要快:但是链表集合在增删值和修改值方面要更灵活,它的原理就好比链条. 3.链表的分类: 3.1单链集合(了解即可):上家能找到下家,但是下家找不到上家,即通过上一个数组可以找到下一个数组,但是没办法通过下一个数组找到上一个数组.如下图: 3.2双链集合:上家能找到下家,下家也能找到上家.如下图: 4.代码实现(以双链为例): 4.1添加值 4

集合框架之数组集合算法

如何检测程序的健康程度? 如果想要知道程序运行所占的CPU和内存的情况可以使用飞行器,这样就可以知道程序的稳定性了.在JDK的bin目录下可以找到飞行器.如下图: 数组集合算法: 1.数组与集合的区别和联系: 数组是有限存储(规定了数组长度就只能存储那么多值),而集合是无限存储,但其实集合也是由数组做成的. 2.数组集合算法的原理: 当向集合里面存储一个值时,集合里面会为其申请一个适当长度的数组来存储,第二次存储值时,如果数组的长度不足以存储第二次的值,就重新申请一个长一点的数组,先把原来的数组