• 最短编辑距离


    题目

    分析

    根据最长公共子序列中状态表示的技巧,本题依旧两个串。状态标识设 dp[i,j] 表示将a[1-i] 变为 b[1-j] 的所有操作方式的集合中最少操作次数。

    其实做了几道线性dp的题目,发现还是有些技巧:就是大都根据最后一个状态或者最后一个或一对元素考虑

    递推公式的推导:考虑元素a[i] 和 b[j]的三种操作

    1. 通过删除a[i] 使得 a[1-i] 变为 b[1-j],意味着a[1-i-1]与b[1-j]已经匹配 。

      dp[i,j] = dp[i-1,j]  + 1

    2. 通过对a数组增加元素使得  a[1-i+1] 变为 b[1-j],意味着a[1-i]与b[1-j-1]已经匹配 

      dp[i,j] = dp[i,j-1]  + 1

    3.通过修改a[i]使得  a[1-i] 变为 b[1-j],意味着[1-i-1]与b[1-j-1]已经匹配 

      dp[i,j] = dp[i,j-1]  + (1/0)       若a[i] == b[j] 则不用加1,若不等则需要改a[i],加1

    最终 dp[i][j] = min(dp[i-1,j]  + 1, dp[i,j-1]  + 1,dp[i,j-1]  + (1/0)   

    代码

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<climits>
     4 using namespace std;
     5 
     6 const int N = 1010;
     7 char a[N],b[N];
     8 int dp[N][N];
     9 int main(){
    10     int n,m;
    11     scanf("%d%s",&n,a+1);
    12     scanf("%d%s",&m,b+1);
    13     //边界初始化 
    14     //若a数组0个元素,则a只能添加操作
    15     for(int i = 0;i <= m;i++) dp[0][i] = i;
    16     //若b数组0个元素,则a只能删除操作
    17     for(int i = 0;i <= n;i++) dp[i][0] = i;
    18     
    19     for(int i = 1;i <= n;i++){
    20         for(int j = 1;j <= m;j++){
    21             dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + 1;
    22             if(a[i] == b[j]){
    23                 dp[i][j] = min(dp[i][j],dp[i-1][j-1]);
    24             }
    25             else{
    26                 dp[i][j] = min(dp[i][j],dp[i-1][j-1]+1);
    27             }
    28                 
    29         }
    30     }
    31     printf("%d",dp[n][m]);
    32     return 0;
    33 }

    注意边界条件!!!第0行或第0列并不一定全为0!!!

    时间复杂度O(N2)

  • 相关阅读:
    select 1 from ... sql语句中的1代表什么意思?
    装饰者模式
    Dao层抽取BaseDao公共方法
    DBUtils工具类
    java Page分页显示
    QTP
    Gym 100513F Ilya Muromets(前缀和)
    AcWing1165 单词环(01分数规划)
    AcWing904 虫洞(spfa判负环)
    AcWing1148 秘密的奶牛运输(次小生成树)
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/14412705.html
Copyright © 2020-2023  润新知