洛谷 P2758 编辑距离

Description

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

  • 删除一个字符;

  • 插入一个字符;

  • 将一个字符改为另一个字符。

求转换的最少操作次数。

\(lenA,lenB \le 2000\),且均只包含小写字母。

Solution

考虑设 \(f[i][j]\) 表示把 \(A\) 中前 \(i\) 个字符变成 \(B\) 中前 j 个字符的最小步数,根据三种操作有转移:

  • 增加:\(f[i - 1][j]\) --> \(f[i][j]\)

即在末尾添上一个与 \(B[j]\) 匹配的字符。

  • 删除:\(f[i][j - 1]\) --> \(f[i][j]\)

即删掉末尾的那个字符。

  • 修改:若 \(a[i] = b[j]\)\(f[i - 1][j - 1]\) --> \(f[i][j]\),否则 \(+1\)

初始值:\(f[i][0] = i\)\(f[0][i] = i\)

如果两串的最后一位相同,我们就不需要花费一次操作,若不同,我们就需要操作一次,使得末尾位相同

Code

// by youyou2007 in 2022.
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#define REP(i, x, y) for(int i = x; i < y; i++)
#define rep(i, x, y) for(int i = x; i <= y; i++)
#define PER(i, x, y) for(int i = x; i > y; i--)
#define per(i, x, y) for(int i = x; i >= y; i--)
#define lc (k << 1)
#define rc (k << 1 | 1)
using namespace std;
/*
inline int read()
{
    int s = 0, w = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}
*/
const int N = 2005;
string a, b;
int lena, lenb;
int f[N][N];
int main()
{
	cin >> a >> b;
	lena = a.length();
	lenb = b.length();
	a = "x" + a;
	b = "x" + b;
	for(int i = 1; i <= lena; i++)//初始值
	{
		f[i][0] = i;		
	}
	for(int i = 1; i <= lenb; i++)
	{
		f[0][i] = i;
	}
	for(int i = 1; i <= lena; i++)
	{
		for(int j = 1; j <= lenb; j++)
		{
			f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
			if(a[i] == b[j])
				f[i][j] = min(f[i][j], f[i - 1][j - 1]);
			else
				f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1); 
		}
	}
	printf("%d", f[lena][lenb]);
	return 0;
}

posted @ 2022-08-10 23:18  panjx  阅读(38)  评论(0编辑  收藏  举报