• [LuoGu] P2758 编辑距离


    (color{red}{mathcal{Description}})

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

    1、删除一个字符;

    2、插入一个字符;

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

    皆为小写字母

    (color{red}{mathcal{Input Format}})

    第一行为字符串 (A) ;第二行为字符串 (B)

    (color{red}{mathcal{Output Format}})

    只有一个正整数,为最少字符操作次数。

    (color{red}{mathcal{DataSize Agreement}})

    字符串 (A)(B) 的长度均小于(2000)

    (color{red}{mathcal{Solution}})

    考虑用dp

    (dp[i][j]) 表示字符串 (A) 的前 (i) 位转换为字符串 (B) 的前 (j) 位需要最小的操作次数

    再考虑状态的转移.这里有个小弯,其实操作一与操作二可以归为一个状态,因为仔细想想就知道没有区别.

    所以得出状态转移方程

    [dp[i][j]=egin{cases}dp[i-1][j-1]&(A[i]=B[j])\max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1&(A[i] eq B[j])end{cases} (1 leq i leq lengthA, 1 leq j leq lengthB) ]

    初始化 (dp[i][0]=i),(dp[0][j]=j) ((1 leq i leq lengthA, 1 leq j leq lengthB))

    (color{red}{mathcal{Code}})

    #include <bits/stdc++.h>
    #define LL long long
    #define reg register
    
    using namespace std;
    
    const int kLen = 2e3 + 10;
    
    int dp[kLen][kLen];
    char A[kLen], B[kLen];
    
    int main() {
      scanf("%s%s", A + 1, B + 1);
      int lena = strlen(A + 1), lenb = strlen(B + 1);
      for (reg int i = 1; i <= lena; ++i)
        dp[i][0] = i;
      for (reg int i = 1; i <= lenb; ++i)
        dp[0][i] = i;
      for (reg int i = 1; i <= lena; ++i)
        for (reg int j = 1; j <= lenb; ++j) {
          if (A[i] == B[j]) {
          	dp[i][j] = dp[i - 1][j - 1];
    	  } else {
    	  	dp[i][j] = min(dp[i - 1][j], min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
    	  }
    	}
      printf("%d
    ", dp[lena][lenb]);
      return 0;
    }
    
    
  • 相关阅读:
    git 常用命令
    目录
    算法--双栈排序
    算法--栈的翻转练习题
    算法--双栈队列
    算法--可查询最值的栈练习题
    Spark算子--union、intersection、subtract
    Spark算子--take、top、takeOrdered
    Spark算子--countByKey
    Spark算子--SortBy
  • 原文地址:https://www.cnblogs.com/1miharu/p/11328951.html
Copyright © 2020-2023  润新知