题解 P2268 [HNOI2002]DNA分子的最佳比对

· · 题解

传送门

题意简述

给你两个字符串

让你插入一个空格、更改一个字符、插入一个新的字符来使这两个字符串有最大匹配数

其中若一个下标上完全匹配加1pts,不同加0pts,若两者中有空格,加-2pts

思路

考虑动态规划

第一个字符串用s1来表示,第二个用s2表示

则动态转移方程: ```c++ f[i][j] = max(f[i - 1][j - 1] + (s[i - 1] == s[j - 1]), f[i][j - 1] - 2, f[i - 1][j] - 2); ``` - $f[i - 1][j - 1] + (s[i - 1] == s[j - 1])$ 表示$s1$第$i$个字符与$s2$第$j$个字符比较(因为循环是从$1$开始,所以字符串的下标要减去1) - $f[i][j - 1]$ 表示$s1$第$i$个字符与空格比较 - $f[i - 1][j]$ 表示$s2$第$j$个字符与空格比较 预处理: ```c++ for (int i = 1; i <= s1.length(); i++) { f[i][0] = f[i - 1][0] - 2; } for (int i = 1; i <= s2.length(); i++) { f[0][i] = f[0][i - 1] - 2; } ``` 即$s1$全部和空格比较,$s2$全部和空格比较 如果懂的话就可以自己写了,否则可能对你的收获不大 还没懂的把上面的代码瞎搞在一起,在自己理解一下,差不多就懂了 注意忽略大小写,否则`70pts` ## 代码 ```c++ #include <bits/stdc++.h> #define MAXN 1010 using namespace std; string s1, s2; int l1, l2; int f[MAXN][MAXN]; int main() { cin >> s1 >> s2; l1 = s1.length(); l2 = s2.length(); //忽略大小写 for (int i = 0; i < l1; i++) { if (s1[i] < 97) s1[i] += 32; } for (int i = 0; i < l2; i++) { if (s2[i] < 97) s2[i] += 32; } //预处理 f[0][0] = 0; for (int i = 1; i <= l1; i++) { f[i][0] = f[i - 1][0] - 2; } for (int i = 1; i <= l2; i++) { f[0][i] = f[0][i - 1] - 2; } //动态规划 for (int i = 1; i <= l1; i++) { for (int j = 1; j <= l2; j++) { int match = 0; if (s1[i - 1] == s2[j - 1]) match = 1; f[i][j] = max(f[i - 1][j] - 2, f[i][j - 1] - 2); f[i][j] = max(f[i][j], f[i - 1][j - 1] + match); } } cout << f[l1][l2] << endl; return 0; } ``` > 日拱一卒,功不唐捐