刚开始对这题毫无头绪,想了几分钟,才意识到可以用求最长公共子序列去做。只要求出LCS,size1+size2-2*LCS即为结果。
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int dp[text2.size()+1],pre,temp,res=0;
memset(dp,0,sizeof(dp));
for(int i=1;i<=text1.size();i++)
{
pre=dp[0];
for(int j=1;j<=text2.size();j++)
{
temp=dp[j];
if(text1[i-1]==text2[j-1])
dp[j]=pre+1;
else
dp[j]=max(dp[j],dp[j-1]);
res=max(dp[j],res);
pre=temp;
}
}
return res;
}
int minDistance(string word1, string word2) {
return word1.size()+word2.size()-2*longestCommonSubsequence(word1,word2);
}
};
做完自己试着画网格分析了直接用动态回归去做(比较笨,只能用例子去归纳),得到下面的状态转移方程
果不其然第一次出错
class Solution {
public:
int minDistance(string word1, string word2) {
int i,j,dp[word1.size()+1][word2.size()+1];
for(i=1;i<=word2.size();i++)
dp[0][i]=i+1;
for(i=1;i<=word1.size();i++)
dp[i][0]=i+1;//这里错误,应该是i。这里是因为一开始没有得到min+1的方程
dp[0][0]=0;
for(i=1;i<=word1.size();i++)
{
for(j=1;j<=word2.size();j++)
{
if(word1[i-1]==word2[j-1])
dp[i][j]=dp[i-1][j-1];
else
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1;
}
}
return dp[i-1][j-1];
}
};
然而,纠正过一些语法之类的错误,后又报错了,因为没考虑空字符串的情况,没法只好打补丁了
class Solution {
public:
int minDistance(string word1, string word2) {
int m=word1.size(),n=word2.size();
if(!m&&!n) return 0;
if(!m) return n;
if(!n) return m;
int i,j,dp[m+1][n+1];
for(i=1;i<=n;i++)
dp[0][i]=i;
for(i=1;i<=m;i++)
dp[i][0]=i;
dp[0][0]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(word1[i-1]==word2[j-1])
dp[i][j]=dp[i-1][j-1];
else
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1;
}
return dp[i-1][j-1];
}
};
结果后面发现,其实开头的判断也不用,之所以遇到空数组出现问题,是我最后返回值有问题,我应该返回dp[m][n],之前忽略了空字符串不仅如此循环的情况。
return dp[m][n];
但是当我想优化这个空间复杂度的时候,遇到了问题,咋弄也没法优化成功,又是打补丁,又是干其他的,都不行。后来发现状态转移方程给搞错了,当然dp[0]和pre的初始化也有问题。唉,在这淦了一个多小时!
class Solution
{
public:
int minDistance(string word1, string word2)
{
int m = word1.size(), n = word2.size();
int temp, pre, i, j, dp[n + 1];
for (i = 0; i <= n; i++)
dp[i] = i;
for (i = 1; i <= m; i++)
{
pre=dp[0];
dp[0]=dp[0]+1;
for (j = 1; j <= n; j++)
{
temp = dp[j];
if (word1[i - 1] == word2[j - 1])
dp[j] = dp[j - 1];
else
dp[j] = min(dp[j - 1], pre) + 1;
pre = temp;
}
}
return dp[n];
}
};
正确的O(n)方法
class Solution
{
public:
int minDistance(string word1, string word2)
{
int m = word1.size(), n = word2.size();
int temp, pre, i, j, dp[n + 1];
for (i = 0; i <= n; i++)
dp[i] = i;
for (i = 1; i <= m; i++)
{
pre=dp[0];
dp[0]=dp[0]+1;
for (j = 1; j <= n; j++)
{
temp = dp[j];
if (word1[i - 1] == word2[j - 1])
dp[j] = pre;
else
dp[j] = min(dp[j - 1], dp[j]) + 1;
pre = temp;
}
}
return dp[n];
}
};