Levenshtein距离只需两行DP数组,因dpi仅依赖dpi-1、dpi、dpi-1;用两个一维vector滚动更新可实现O(min(m,n))空间复杂度,需正确初始化边界并处理UTF-8多字节字符陷阱。

Levenshtein 距离为什么只需要两行 DP 数组
因为状态转移只依赖上一行和当前行的左侧值,dp[i][j] 仅由 dp[i-1][j](删)、dp[i][j-1](增)、dp[i-1][j-1](替)决定。整张二维表按行滚动计算时,存满两行足矣——旧的“上一行”在算完当前行后就可被覆盖。
如何用 vector> 实现空间 O(min(m,n)) 的滚动更新
实际不需要固定两行,只需两个一维 vector<int></int>:一个叫 prev(上一行),一个叫 curr(当前行)。为最小化空间,先确保 s1 是较短串,让 prev 和 curr 长度为 s1.length() + 1;否则交换输入顺序再算。
常见错误现象:std::out_of_range 或结果偏大,多因未正确初始化首行/首列,或错把 s1 当长串导致数组越界。
-
prev[j]初始为j(空串转 s1[0..j-1] 需 j 次插入) - 循环中,
curr[0]始终为i(s1 转空串需 i 次删除) - 字符相等时,
curr[j] = prev[j-1];否则取三者最小值加 1
避免拷贝开销的 in-place 优化写法
不用每次 swap(prev, curr) 后清空 curr,而是复用同一块内存,用指针切换语义:
vector<int> row0(n + 1), row1(n + 1); vector<int> *prev = &row0, *curr = &row1; for (int i = 1; i <p>性能影响:省去 vector resize 和元素拷贝,对长字符串(如 >10k 字符)差异明显;兼容性无问题,C++11 起均可运行。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a> <p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <h3>边界 case 和字符类型陷阱</h3> <p>Levenshtein 本身不关心字符编码,但 C++ 中若传入 <code>std::string</code> 含 UTF-8 多字节字符(如中文),直接按字节比会出错——此时 <code>s1[j-1] == s2[i-1]</code> 比的是单个字节而非完整码点。</p> <p>使用场景若涉及非 ASCII 文本,必须先转为 Unicode 码点序列(如用 <code>std::u32string</code> 或第三方库解析 UTF-8),否则距离计算无意义。</p> <p>容易被忽略的地方:当任一输入为空串时,返回另一串长度即可,不必进主循环;但若提前没判空,<code>row0</code> 或 <code>row1</code> 构造时 <code>n+1</code> 为 1,仍能跑通——只是多做了几轮无意义迭代。</p></int></int>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










