zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    leetcode--Populating Next Right Pointers in Each Node II
    leetcode—Populating Next Right Pointers in Each Node
    Pascal's Triangle II
    leetcode—pascal triangle
    leetcode—triangle
    October 23rd, 2017 Week 43rd Monday
    October 22nd, 2017 Week 43rd Sunday
    October 21st 2017 Week 42nd Saturday
    October 20th 2017 Week 42nd Friday
    October 19th 2017 Week 42nd Thursday
  • 原文地址:https://www.cnblogs.com/little-w/p/3449389.html
Copyright © 2011-2022 走看看