#luoguP2758. 编辑距离
编辑距离
你好,同学。针对你在二维 DP 转移来源上的薄弱点,我们今天重点攻克 P2758 编辑距离。这道题是字符串处理类 DP 的教科书级题目,它能完美解决你对“左、上、左上”来源的选择困惑。
第一部分:NOI 规范题面
【题目描述】
设 和 是两个字符串。我们要用最少的字符操作次数,将字符串 转换为字符串 。字符操作共有三种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符。
均只包含小写字母。
【输入格式】
共两行,每行一个字符串,分别表示 和 。
【输出格式】
一个整数,表示最少操作次数。
【输入输出样例 #1】
输入 #1
sfdqxbw
gfdgw
输出 #1
4
【数据规模与约定】
对于 的数据,。 时间限制:,内存限制:。
第二部分:预备知识点
- 二维状态定义:理解
dp[i][j]代表 A 串前 个字符变换到 B 串前 个字符的最小代价。 - 边界处理:当其中一个字符串为空时,变换代价即为另一个字符串的长度。
- 多来源决策(Min 决策):在三种物理操作(增、删、改)中寻找最优解。
- 1-based Indexing:在处理字符串 DP 时,通常将下标从 1 开始,保留第 0 行/列作为边界。
第三部分:启发式思维引导(草稿纸上的推理)
请拿出一张草稿纸,跟我一起画出这个思维过程:
Step 1: 建立坐标系
画一个表格,纵轴代表字符串 (长度 ),横轴代表字符串 (长度 )。 提问:如果 是空串(长度为 0),变成长度为 的 串需要几步? 行动:在第一行填入 (全是插入操作)。同理,第一列填入 (全是删除操作)。
Step 2: 核心决策分析
假设我们正在处理 dp[i][j](即 要匹配 ),此时纸上有三个相邻的状态:
-
左上方
dp[i-1][j-1](双向同步):- 如果 ,不需要任何操作。状态直接继承:
dp[i][j] = dp[i-1][j-1]。 - 如果 ,进行“替换”操作。代价:
dp[i-1][j-1] + 1。
- 如果 ,不需要任何操作。状态直接继承:
-
上方
dp[i-1][j](只删 A):- 代表 的前 个字符已经匹配了 的前 个。现在多出了 ,必须删除它。代价:
dp[i-1][j] + 1。
- 代表 的前 个字符已经匹配了 的前 个。现在多出了 ,必须删除它。代价:
-
左方
dp[i][j-1](只加 A):- 代表 的前 个已经匹配了 的前 个。现在 B 还多一个 ,必须在 A 后面插入一个。代价:
dp[i][j-1] + 1。
- 代表 的前 个已经匹配了 的前 个。现在 B 还多一个 ,必须在 A 后面插入一个。代价:
Step 3: 复杂度思考
- 空间: 的
int数组约占用 ,远小于 。 - 时间:双重循环,复杂度 ,约 次运算,在 内绰绰有余。
第四部分:逻辑流程图 (Mermaid)
为了避免特殊符号报错,我使用了文字描述逻辑。
graph TD
Start("开始 (Standard C++14)") --> ReadStr("读取 A 串和 B 串")
ReadStr --> GetLen("获取长度 n 和 m")
subgraph Initialization ["初始化阶段"]
InitCol("循环 i 从 0 到 n: dp_i_0 = i (删除操作)")
InitRow("循环 j 从 0 到 m: dp_0_j = j (插入操作)")
end
GetLen --> InitCol
InitCol --> InitRow
subgraph DP_Loop ["状态转移嵌套循环"]
OuterLoop("外层: i 从 1 到 n")
InnerLoop("内层: j 从 1 到 m")
CheckMatch{"判断 A_i-1 是否等于 B_j-1"}
Source1("相等: dp_i_j = dp_i-1_j-1")
Source2("不等: dp_i_j = min(左, 上, 左上) + 1")
end
InitRow --> OuterLoop
OuterLoop --> InnerLoop
InnerLoop --> CheckMatch
CheckMatch -- "是" --> Source1
CheckMatch -- "否" --> Source2
Source1 --> NextJ("j 循环结束?")
Source2 --> NextJ
NextJ -- "否" --> InnerLoop
NextJ -- "是" --> NextI("i 循环结束?")
NextI -- "否" --> OuterLoop
NextI -- "是" --> Output("输出 dp_n_m")
Output --> End("结束")
第五部分:读题关键词与技巧总结
在做 NOI 级别的 DP 题时,通过关键词快速定位:
- “最少操作次数”:典型的最优性问题,考虑 DP。
- “字符串 A 转换为 B”:双序列匹配 DP。
- “插入、删除、修改”:
- 插入/删除:对应 DP 表的水平或垂直移动(只消耗一个序列)。
- 修改/匹配:对应 DP 表的斜对角线移动(同时消耗两个序列)。
- 数据范围 :
- 这是暗示 算法的标志性数字。如果范围是 ,则需要考虑贪心 + 二分或其它高级优化。
教练提示:你之前错在字符相等时加了 +1。记住:DP 转移的本质是“物理动作的代价”。如果两个字符已经相等,你“不需要做任何动作”,所以代价是 +0。请在做这题时,务必在草稿纸上模拟相等字符的跳转逻辑!加油!