题目描述
给定一个长度为 $n$ 的字符串 $a$ 和一个长度为 $m$ 的字符串 $b$,每次操作可以更换字符串 $a$ 中的一个字符,求令 $a$ 串包含 $b$ 串的最少操作次数。
$1 \leq m \leq n \leq 1000$
输入样例
ABCDEABCD
XAABZ
输出样例
3
DP
这题大概是 编辑距离 的稍微变形
我居然不会做qwq,感谢nb裙友的帮助。
直接按照求的结果定义状态 $f[i][j]$ 为使得 $a$ 串的前 $i$ 个字符包含 $b$ 串的前 $j$ 个字符的最小操作次数
具体状态转移可以看完整代码
注意对于任意的 $i \in N$ 有 $f[i][0] = 0$ (空串是任何串的子串)
时间复杂度 $O(nm)$
C++ 代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
char a[N], b[N];
int f[N][N]; // f[i][j]为使得a串的前i个字符包含b串的前j个字符的最小操作次数
int main()
{
scanf("%s%s", a + 1, b + 1);
int n = strlen(a + 1), m = strlen(b + 1);
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for(int i = 1; i <= n; i ++)
{
f[i][0] = 0;
for(int j = 1; j <= m; j ++)
{
f[i][j] = f[i - 1][j];
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\n", f[n][m]);
return 0;
}
大佬为什么要打上f[i][0] = 0?
是考虑到万一第二个字串为空的情况下,所以初始化f[i][0] = 0吗?
请问为什么dou初始化inf
scanf(“%s%s”, a + 1, b + 1); 这里ab +1是为什么啊
字符串下标从1开始
大佬你好,我考虑状态转移的时候想的是f[i][j]可以从
f[i - 1][j]
、f[i - 1][j - 1]
、f[i][j - 1]
这三种状态转移过来,前两种在您的代码里都有体现。那请问要考虑
f[i][j - 1]
转移到f[i][j]
的这种情况吗?可以不考虑,考虑了反而不好转移
f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1);这里为什么是这两个数间的最小值呢?直接f[i][j] = f[i - 1][j - 1] + 1行嘛?
前面有个
f[i][j] = f[i - 1][j]
,所以实际上是f[i][j] = min(f[i - 1][j], f[i - 1][j - 1] + 1
,可以从这两种情况转移过来,取较小值原来如此,谢了
f[i][j] = f[i - 1][j]; 请问这个转移是这么来的呢?
a串包含b串的话那么a串后面多一个字母同样包含b串
所以令a[1, i]包含b[1, j]的操作数可以等于令a[1, i - 1]包含b[1, j]的操作数
qwq突然发现抽风也是大括号换行的。
(顺便楼下啥情况)
2333我代码风格都是野生的
(顺便楼下啥情况)
老婆厉害!!!!
wdnmd