字符串相似度算法 递归与动态规划求解分析

1.概念

  编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括:(1)将一个字符替换成另一个字符,(2)插入一个字符,(3)删除一个字符。

  相似度,等于“编辑距离+1”的倒数。

2.分析

  设有字符串a[0...n],b[0...m]。

  (1)当a[i]=b[j]时,说明这时候不需要编辑操作。编辑距离保持,即f(i,j)=f(i-1,j-1)

  (2)当a[i]!=b[j]时,可以有三种编辑操作。

  其中删除和插入操作,只对一个下标i或者j产生影响。如在下图中,当前匹配到(t1,t2)处,如果采用删除'g',只改变t1的下标。

  

   其中替换操作,会对2个下标都产生影响。如在下图中,当前匹配到(t1,t2)处,如果将'g'替换成'm',则下次就需要执行(t1+1,t2+1)处。

     

   所以可以推导出下面就是递推公式。

  

3.用递归求解代码

#include<stdio.h>
#include<string.h>
char *a="abcgh";
char *b="aecdgh";
int min(int t1,int t2,int t3)   ///求三个数的最小值
{
    int min;
    min=t1<t2?t1:t2;
    min=min<t3?min:t3;
    return min;
}
int calculate(int i,int enda,int j,int endb)
{
    int t1,t2,t3;
    if(i>enda)  ///i指示超过a[]的范围时
    {
        if(j>endb)
            return 0;
        else
            return endb-j+1;
    }
    if(j>endb)  ///j指示超过b[]的范围时
    {
        if(i>enda)
            return 0;
        else
            return enda-i+1;
    }
    if(*(a+i) == *(b+j))    ///如果两个相等,则直接求下一个位置
        return calculate(i+1,enda,j+1,endb);
    else
    {
        t1=calculate(i+1,enda,j,endb);  ///删除a[i]或在b中插入a[i]
        t2=calculate(i,enda,j+1,endb);  ///删除b[j]或在a中插入b[j]
        t3=calculate(i+1,enda,j+1,endb);    ///替换
        return 1+min(t1,t2,t3);
    }
}
int main()
{
    int dis=calculate(0,strlen(a)-1,0,strlen(b)-1);
    printf("dis=%d",dis);
    return 1;
}

 4.用动态规划求解代码

 

#include<stdio.h>
#include<string.h>
#define MAX 1000
int dp[MAX][MAX];   ///dp[i][j]表示当前a[0..i-1]与b[0..j-1]的编辑距离
char *a="agbgd";
char *b="ggd";

int min(int t1,int t2,int t3)   ///求三个数的最小值
{
    int min;
    min=t1<t2?t1:t2;
    min=min<t3?min:t3;
    return min;
}

int main()
{
    int i,j;
    int lena=strlen(a),lenb=strlen(b);
    memset(dp,0,sizeof(dp));
    for(i=0;i<=lena;i++)   ///a作为行,当b为空串时
        dp[0][i]=i;
    for(i=0;i<=lenb;i++)   ///b作为列,当a为空串时
        dp[i][0]=i;

    for(i=1;i<=lena;i++)
    {
        for(j=1;j<=lenb;j++)
        {
            if(*(a+i)==*(b+j))  ///相等时
                dp[i][j]=dp[i-1][j-1];
            else
                dp[i][j]=1+min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]); ///不相等时,取三种可能操作的最小数值+1
        }
    }
    printf("编辑距离为:dis=%d\n",dp[lena][lenb]);
    return ;
}

 类似有:  最长公共子序列求解:递归与动态规划方法

时间: 2024-09-20 16:33:34

字符串相似度算法 递归与动态规划求解分析的相关文章

java字符串相似度算法_java

本文实例讲述了java字符串相似度算法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: public class Levenshtein {     private int compare(String str, String target) {         int d[][]; // 矩阵         int n = str.length();         int m = target.length();         int i; // 遍历str的      

计算字符串相似度算法—Levenshtein

什么是Levenshtein Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符.levenshtein() 函数返回两个字符串之间的 Levenshtein 距离.编辑距离的算法是首先由俄国科学家Levenshtein提出的,故又叫Levenshtein Distance 实现过程 首先我们明确从一个字符串变化到另一个字符串需要进行添加.修改.删除来变化 如a变化到

PHP中计算字符串相似度的函数代码_php技巧

similar_text - 计算两个字符串的相似度 int similar_text ( string $first , string $second [, float &$percent ] ) $first 必需.规定要比较的第一个字符串. $second 必需.规定要比较的第二个字符串. $percent 可选.规定供存储百分比相似度的变量名. 两个字符串的相似程度计算依据 Oliver [1993] 的描述进行.注意该实现没有使用 Oliver 虚拟码中的堆栈,但是却进行了递归调用,这

计算字符串相似度的简易算法

算法设计背景: 最近设计知识管理系统的资源导入功能,为了尽量的做到组件化,方便扩展,方便其他模块使用.简 化组件提供的和需要的接口,设计并实现了基于 Mapping 机制的导入框架.其中有一功能用到了计算两 个字符串相似度的算法,简单设计如下以便参考: 设计思想: 把两个字符串变成相同的基本操作定义如下: 1.修改一个字符(如把 a 变成 b) 2.增加一个字符 (如 abed 变成 abedd) 3.删除一个字符(如 jackbllog 变成 jackblog) 针对于 jackbllog到j

经典算法题每日演练——第五题 字符串相似度

        这篇我们看看最长公共子序列的另一个版本,求字符串相似度(编辑距离),我也说过了,这是一个非常实用的算法,在DNA对比,网 页聚类等方面都有用武之地. 一:概念      对于两个字符串A和B,通过基本的增删改将字符串A改成B,或者将B改成A,在改变的过程中我们使用的最少步骤称之为"编辑距离". 比如如下的字符串:我们通过种种操作,痉挛之后编辑距离为3,不知道你看出来了没有? 二:解析   可能大家觉得有点复杂,不好理解,我们试着把这个大问题拆分掉,将"字符串

算法实现-求解利用最长公共子序列进行字符串重排序算法的代码

问题描述 求解利用最长公共子序列进行字符串重排序算法的代码 利用合并LCS表求出一张基于所给连接词二进制的表,利用这张表和连接词k再反过来求出LCS表

关于字符串操作的算法题目

原题链接: http://oj.leetcode.com/problems/interleaving-string/ 这是一道关于字符串操作的题目,要求是判断一个字符串能不能由两个字符串按照他们自己的顺序,每次挑取两个串中的一个字符来构造出来. 像这种判断能否按照某种规则来完成求是否或者某个量的题目,很容易会想到用动态规划来实现. 先说说维护量,res[i][j]表示用s1的前i个字符和s2的前j个字符能不能按照规则表示出s3的前i+j个字符,如此最后结果就是res[s1.length()][s

【算法导论】动态规划算法之装配线调度

        和分治算法一样,动态规划是通过组合子问题的解而解决整个问题的.但是与分治算法不同的是,动态规划算法适用于子问题不是独立的情况,也就是各子问题包含公共的子子问题.动态规划通常用于最优化问题的求解.看一个问题是否适合采用动态规划算法,主要有两个标志:最优子结构和重叠子问题. 最优子结构:问题的一个最优解包含了子问题的最优解. 重叠子问题:当一个递归算法不断地调用同一问题时,我们说该最优子问题包含重叠子问题. 动态规划算法的设计步骤如下: 1.描述最优解的结构. 2.递归定义最优解的值

算法起步之动态规划

原文:算法起步之动态规划        动态规划其实是类似于分治算法,说白就是要解决这类问题需要依赖一个个的子问题解决.动态规划通常是用来求解最优化问题,设计一个动态规划的算法一般需要四步: 刻画一个最优解的结构特征. 递归定义最优解的值. 计算最优解的值采用自底向上的方法. 利用计算出的信息构造一个最优解.       但是一般我们只需要前三步即可,第4步是根据最优值来求最优解的构成.       我们先通过一个具体的例子来了解一下.       下图是某公司出售的一段长度为i英寸的共条的价格