zoukankan      html  css  js  c++  java
  • 蓝桥杯 最优包含

    这一题类似于距离编辑,所以我们首先来看看什么是编辑距离。


    题目 2141: [信息学奥赛一本通-T1276 ]编辑距离  https://www.dotcpp.com/oj/problem2141.html

    题目描述
    设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:

        1、删除一个字符;

        2、插入一个字符;

        3、将一个字符改为另一个字符。


    对任意的两个字符串A和B,计算出将字符串A变换为字符串B所用的最少字符操作次数。
    解决思路:
      dp求解。设dp[ i ][ j ]为将字符串A[ 1,...,i ] 转变为字符串 B[ 1,...,j ]所用的最小字符操作次数。
        边界情况:
        dp[ 0 ][ 0 ] = 0 (两个空串)
        dp[ i  ][ 0 ] = i (对A[ 1,...,i ] 重复进行 i 次删除操作)
        dp[ 0 ][  j ] = j (对空串A重复进行 j 次插入操作) 
        递推式:
        dp[ i ][ j ] = dp[ i ][ j-1 ] + 1 ( 在A[ 1,...,i ]的尾部插入B[ j ] )
        dp[ i ][ j ] = dp[ i-1 ][ j ] + 1  ( 删去A[ 1,...,i ]的尾部A[ i ] ) 
        dp[ i ][ j ] = dp[ i-1 ][ j-1 ] + (A[ i ]==B[ j ] ? 0 : 1 ) (如果不相等则将A[ i ]替换为B[ j ],否则不需要替换 )
        dp[ i ][ j ] 在上述三种可能中取最小(对应于三种操作)
    实现代码:
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int Max_N = 2e3+10;
    
    char A[Max_N],B[Max_N];
    int  dp[Max_N][Max_N];
    
    int main()
    {
        scanf("%s%s",A+1,B+1);//下标从1开始 便于操作 
        int len_A = strlen(A+1), len_B = strlen(B+1);
        //边界情况
        dp[0][0] = 0;
        for( int i=1; i<=len_A; i++ )    dp[i][0] = i;
        for( int j=1; j<=len_B; j++ )    dp[0][j] = j;
        //递推式
        for( int i=1; i<=len_A; i++ )
        {
            for( int j=1; j<=len_B; j++ )
            {
                int temp = min( dp[i][j-1], dp[i-1][j] ) + 1;
                int d = A[i]==B[j] ? 0 : 1;
                dp[i][j] = min( temp, dp[i-1][j-1]+d );
            }    
        } 
        printf("%d
    ",dp[len_A][len_B]);
        return 0;
    } 

    最优包含 https://www.acwing.com/problem/content/2555/

    2553. 最优包含

    我们称一个字符串 S 包含字符串 是指 T 是 S 的一个子序列,即可以从字符串 S 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 T 完全一样。

    给定两个字符串 S 和 T,请问最少修改 S 中的多少个字符,能使 S 包含 T?


    解题思路:
      与编辑距离不同的是题目只要求包含且只有替换操作。仍然用dp方法。
      设dp[ i ][ j ] : S[ 1,...,i ]需要修改多少个字符能包含T[ 1,...,j ]
      边界情况:
      dp[ i ][ 0 ] = 0 (不需要替换)
      dp[ i ][ j ]  = INF i<=j or len_S-i <= len_T-j (我当时遇到的问题就是如何保证S中有足够的字符能替换为T,只需要保证i>=j即之前
    有足够字符且len_S-i <= len_T-j 即之后有足够字符,实现时只需要将边界dp[ 0 ][ j ] = INF )
      递推式:
      dp[ i ][ j ] = dp[ i-1 ][ j ] (S[ 1,...,i-1 ]已经包含了T[ 1,...,j ] )
      dp[ i ][ j ] = dp[ i-1 ][ j-1 ] + (S[ i ]==T[ j ] ? 0 : 1 )
    实现代码:
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int INF = 1e8+10; 
    const int Max_N = 1e3+10;
    
    char S[Max_N],T[Max_N];
    int dp[Max_N][Max_N];
    
    int main()
    {
        scanf("%s%s",S+1,T+1);
        int len_S = strlen(S+1), len_T = strlen(T+1);
        
        //初始化
        dp[0][0] = 0;
        for( int i=1; i<=len_S; i++ )    dp[i][0] = 0;
        for( int j=1; j<=len_T; j++ )    dp[0][j] = INF;
        //递推 
        for( int i=1; i<=len_S; i++ )
        {
            for( int j=1; j<=len_T; j++ )
            {
                int d = S[i]==T[j] ? 0 : 1;
                dp[i][j] = min( dp[i-1][j], dp[i-1][j-1]+d ); 
            }
        }
        printf("%d
    ",dp[len_S][len_T]);
        return 0;
    }

    参考连接 https://www.cnblogs.com/biyeymyhjob/archive/2012/09/28/2707343.html

  • 相关阅读:
    高数——微分方程的通解和特解
    高数——求极限的方法
    算法训练——删除数组零元素
    算法训练——输出米字形
    算法训练——数的统计
    算法训练——数对
    算法训练——数组查找及替换
    算法训练——数组排序去重
    算法训练——素因子去重
    算法训练——特殊的数字四十
  • 原文地址:https://www.cnblogs.com/w-like-code/p/14613804.html
Copyright © 2011-2022 走看看