P2758 编辑距离

题目传送门

思路:

这道题是经典的编辑距离问题(Edit Distance),通常使用动态规划(Dynamic Programming, DP)来解决。编辑距离是指将一个字符串转换成另一个字符串所需的最少操作次数,操作包括插入、删除和替换字符。

思路

  1. 定义状态

    • 设 dp[i][j] 表示将字符串 A 的前 i 个字符转换成字符串 B 的前 j 个字符所需的最少操作次数。
  2. 状态转移方程

    • 如果 A[i-1] == B[j-1],则 dp[i][j] = dp[i-1][j-1],因为当前字符相同,不需要额外操作。
    • 如果 A[i-1] != B[j-1],则需要考虑三种操作:
      • 插入:dp[i][j] = dp[i][j-1] + 1,即在 A 的第 i 个位置插入一个字符使得 A[i] == B[j-1]
      • 删除:dp[i][j] = dp[i-1][j] + 1,即删除 A 的第 i 个字符。
      • 替换:dp[i][j] = dp[i-1][j-1] + 1,即将 A 的第 i 个字符替换为 B 的第 j 个字符。
    • 综上,dp[i][j] = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + 1
  3. 初始化

    • dp[0][j] = j,即将空字符串转换为 B 的前 j 个字符需要 j 次插入操作。
    • dp[i][0] = i,即将 A 的前 i 个字符转换为空字符串需要 i 次删除操作。
  4. 结果

    • dp[len(A)][len(B)] 即为将字符串 A 转换为字符串 B 所需的最少操作次数。

Python代码(现打的,WA了不怪我):

def edit_distance(A, B):
    len_A = len(A)
    len_B = len(B)
    
    # 创建一个 (len_A + 1) x (len_B + 1) 的二维数组
    dp = [[0] * (len_B + 1) for _ in range(len_A + 1)]
    
    # 初始化
    for i in range(len_A + 1):
        dp[i][0] = i
    for j in range(len_B + 1):
        dp[0][j] = j
    
    # 状态转移
    for i in range(1, len_A + 1):
        for j in range(1, len_B + 1):
            if A[i - 1] == B[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1
    
    return dp[len_A][len_B]

# 输入
A = input().strip()
B = input().strip()

# 输出
print(edit_distance(A, B))

 

Pascal代码(现打的,WA了不怪我):

program EditDistance;

var
  A, B: string;
  len_A, len_B: integer;
  dp: array[0..2000, 0..2000] of integer;
  i, j: integer;

begin
  readln(A);
  readln(B);
  
  len_A := length(A);
  len_B := length(B);
  
  // 初始化
  for i := 0 to len_A do
    dp[i, 0] := i;
  for j := 0 to len_B do
    dp[0, j] := j;
  
  // 状态转移
  for i := 1 to len_A do
    for j := 1 to len_B do
      if A[i] = B[j] then
        dp[i, j] := dp[i - 1, j - 1]
      else
        dp[i, j] := min(dp[i - 1, j] + 1, min(dp[i, j - 1] + 1, dp[i - 1, j - 1] + 1));
  
  writeln(dp[len_A, len_B]);
end.

c++代码(100pts): 

#include<iostream>
#include<istream>
#include<ostream>
#include<string>
#include<algorithm>
#include<bitset>
#include<cmath>
#include<queue>
#include<map>
#include<iomanip>
#include<cstdio>
#include<cstring>
using namespace std;
int f[5000][5000];                                                                           //f表示将str串的前x个字符改成target串最少需要多少步
char str[5000],target[5000];                                                                 //str:原来的字符串,target:改后的字符串
int main(){                                                                                  //主函数
	cin>>str;                                                                                //输入原来的字符串
	cin>>target;                                                                             //输入改后的字符串

	for(int i = 1;i <= strlen(str);i++) f[i][0] = i;                                         //删i个字符,编辑距离为i
	for(int i = 1;i <= strlen(target);i++) f[0][i] = i;                                      //同上
	
	for(int i = 1;i <= strlen(str);i++){
		for(int j = 1;j <= strlen(target);j++){
			if(str[i - 1] == target[j - 1]) f[i][j] = f[i - 1][j - 1];                       //如果两个字符串的第i个字符一样,就不用改距离
			else f[i][j] = min(min(f[i - 1][j - 1] + 1,f[i - 1][j] + 1),f[i][j - 1] + 1);    //找删字符、插入字符、替换字符中操作次数的最小值
		}
	}
	
	cout<<f[strlen(str)][strlen(target)]<<endl;                                              //输出需要最少的操作次数(最小的编辑距离)
	return 0;
}

制作不易, 蒟蒻题解,神犇勿喷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值