• SPOJ 6219 Edit distance字符串间编辑距离


    题目地址http://www.spoj.com/problems/EDIST/

    题目描述:给定字符串s1,字符串s2(长度<=2000)

    求将s1转换为s2最小操作数:1、添加一个字符;2、删除一个字符;3、变更一个字符

    分析最优子结构

    dp[i][j]为s1串到第i个位置,s2到第j个位置时的最小布数,

    则dp (i,j)=   dp(i-1,j-1),s1(i)==s2(j)

                             min(dp(i-1,j)+1,dp(i,j-1)+1 ) ,s1(i)!=s2(j)

    还是来分析前一个状态的最优子结构:

    例如:s1=“asdfas”

             s2=“axefsa”

    如果s1(i)=s2(j),不用做任何操作。即使前面出现了“asda”,“fewaa”这种情况dp(4,5)=dp(3,4)都能保证依旧最优解因为s2最多有1个‘a’与s1的‘a’配对,

                                     反过来想,前面dp(i-1,j-1)已经保证了最优子结构,且前面的dp(i-1,j-1)对后面的s1(i),s2(j)无影响。

          s1(i)!=s2(j),则有3种选择:

    dp(i)(j)=

    1、s1(i)变成s2(j),dp(i-1)(j-1)+1;

    2、在s1中删除s1(i),dp(i-1)(j)+1,暗含一个条件,即删除s1(i)后s1‘与s2'是相同的那么说明在dp(i-1)(j)中形成的两个串和删除s1(i)的两个串是一样的,所以和现在s1(i)无关,所以前一个最优状态是dp(i-1)(j)

    3、在s1中第i个位置上添加一个s2(j),dp(i)(j-1)+1,那说明什么呢?当我们要判断s2(j)时发现s1‘上少了一个和s2(j)相同的字母。

    想一想,已经没有其他可供修改的操作了,所以是在这枚举这3种后取一个最小值。

    递推代码:

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    int c[2005][2005];
    char s1[2005],s2[2005];
    int mins(int a,int b,int c){
        if (a<=b && a<=c) return a;
        else if (b<=c) return b;else return c;
    }
    int dp(int l,int r){
        c[0][0]=0;//边界处理
        for(int i=1;i<=l;i++)c[i][0]=i;//表示s1要删除的个数为i
        for(int j=1;j<=r;j++)c[0][j]=j;//s1要添加的个数为j
        for(int i=1;i<=l;i++){
            for(int j=1;j<=r;j++)
            if(s1[i-1]==s2[j-1]) c[i][j]=c[i-1][j-1];//递推
            else c[i][j]=mins(c[i-1][j-1]+1,c[i][j-1]+1,c[i-1][j]+1);
        }
        return c[l][r];
    }
    int main(){
    //    freopen("in","rb",stdin);
    //    freopen("out","wb",stdout);
        int t;
        scanf("%d",&t);
        while(~scanf("%s%s",s1,s2)){
            int l=strlen(s1),r=strlen(s2);
            printf("%d
    ",dp(l,r));
    
        }
        return 0;
    }
    

      递归代码:

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    int c[2005][2005];
    int vis[2005][2005];
    char s1[2005],s2[2005];
    int mins(int a,int b,int c){
        if (a<=b && a<=c) return a;
        else if (b<=c) return b;else return c;
    }
    int dp(int l,int r){
        int &ans=c[l][r];
        if (vis[l][r]) return ans;
        vis[l][r]=1;
        if (l==0) return ans=r;
        if (r==0) return ans=l;
        if (s1[l-1]==s2[r-1]) ans=dp(l-1,r-1);
        else ans=mins(dp(l,r-1)+1,dp(l-1,r)+1,dp(l-1,r-1)+1);
        return ans;
    }
    int main(){
    //    freopen("in","rb",stdin);
    //    freopen("out","wb",stdout);
        int t;
        scanf("%d",&t);
        while(~scanf("%s%s",s1,s2)){
            int l=strlen(s1),r=strlen(s2);
            memset(vis,0,sizeof(vis));
            printf("%d
    ",dp(l,r));
    
        }
        return 0;
    }
    

      

  • 相关阅读:
    文件查找和比较命令 来自: http://man.linuxde.net/find
    Docker学习计划
    Mybatis各种模糊查询
    linux下vi命令大全
    mac下的环境变量
    slf4j输出变量
    使用lombok中的log
    idea中的java web项目(添加jar包介绍)和java maven web项目目录结构
    slf4j+logback&logback.xml
    日志框架
  • 原文地址:https://www.cnblogs.com/little-w/p/3449389.html
Copyright © 2020-2023  润新知