zoukankan      html  css  js  c++  java
  • 最短编辑距离

    题目

    分析

    根据最长公共子序列中状态表示的技巧,本题依旧两个串。状态标识设 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)

  • 相关阅读:
    cmd net use
    Linux虚拟机安装VMware Tools
    转:完成端口(Completion Port)详解
    很幽默的讲解六种Socket IO模型
    重新学习二叉树作的几道习题
    RuntimeException和Exception区别
    不同概率的抽奖
    SpringMVC的几种返回方式
    mybatis动态sql trim
    Tomcat 7最大并发连接数的正确修改方法
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/14412705.html
Copyright © 2011-2022 走看看