即寻找两个字符串之间的编辑距离。编辑距离定义:函数
编辑距离是针对二个字符串(例如英文字)的差别程度的量化量测,量测方式是看至少须要多少次的处理才能将一个字符串变成另外一个字符串。
如:kitten
和sitting
的最小编辑距离是3。spa
经典动态规划问题。将长度为m
字符串S
变成长度为n
字符串T
,其状态转移方程为:code
$$ f(i,j) = \begin{cases} \sum_{k=1}^i CostOfDel(T_k) & \text{if $j = 0$ } \\[2ex] \sum_{k=1}^j CostOfIns(S_k) & \text{if $i = 0$ } \\[2ex] min \begin{cases} f(i-1,j)+CostOfDel(T_i) \\[2ex] f(i,j-1)+CostOfIns(S_j) \\[2ex] f(i-1,j-1)+CostOfSub(S_j,T_i) & \text{if $S_j \neq T_i$ } \\[2ex] f(i-1,j-1) & \text{if $S_j = T_i$ } \\[2ex] \end{cases} & \text{ others } \\[2ex] \end{cases} $$ip
f(i,j)
表明字符串S
的长度为j
的前缀子串变成字符串T
的长度为i
的前缀子串的最小编辑代价。leetcode
答案即f(n,m)
。状态数mn
个,状态转移复杂度O(1)
,所以时间复杂度为O(mn)
,空间复杂度为O(min(m,n))
。
此题中全部Cost*
函数的返回值都是1
。则状态转移方程可简化为字符串
$$ f(i,j) = \begin{cases} i & \text{if $j = 0$ } \\[2ex] j & \text{if $i = 0$ } \\[2ex] f(i-1,j-1) & \text{if $S_j = T_i$ } \\[2ex] min \begin{cases} f(i-1,j)+1 \\[2ex] f(i,j-1)+1 \\[2ex] f(i-1,j-1)+1 \\[2ex] \end{cases} & \text{if $S_j \neq T_i$ } \\[2ex] \end{cases} $$get
#include <algorithm> class Solution { typedef int len_type; public: int minDistance(const string& src, const string& dest) { if (dest.size() > src.size()) { return minDistance(dest, src); } if (!dest.size()) return src.size(); if (!src.size()) return dest.size(); len_type len_src = src.size(), len_dest = dest.size(); len_type* const pc = new len_type[len_dest]; char c = src[0]; pc[0] = (c != dest[0]); for (len_type j = 1; j < len_dest; ++j) pc[j] = std::min((c != dest[j]) + j, pc[j - 1] + 1); for (len_type i = 1; i < len_src; ++i) { char c = src[i]; len_type lastj = pc[0]; pc[0] = std::min((c != dest[0]) + i, lastj + 1); for (len_type j = 1; j < len_dest; ++j) { len_type samej = pc[j]; pc[j] = std::min((c != dest[j]) + lastj, std::min(pc[j - 1], samej) + 1); lastj = samej; } } len_type dist = pc[len_dest - 1U]; delete [] pc; return dist; } };
主要应用了动态规划的思想。string