给定一个源串和目标串,能对源串进行如下操作:
1.在给定位置插入一个字符
2.替换任意字符
3.删除任意字符
写一个程序,返回最小操作次数,使得对源串进行这些操作后等于目标串。源串和目标串的长度都小于2000。
CVTE遇到的一道笔试题,用动态规划
1.状态:dp[i][j] 表示的是从源串s[0.....i]变成目标串t[0....j]的最小编辑次数
2.边界条件:dp[0][j] = j ,dp[i][0] = 0
3.状态转移方程:dp[i][j] = min{dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1或0(如果s[i]=t[j]就加0,不等就加1) }
例如,把字符串"ALGORITHM"变成"ALTRUISTIC",可以先把相关字符各自对齐。
A L G O R I T H M
A L T R U I S T I C
然后把上面的源串S[0..i]="ALGORITHM"编辑成下面的目标串T[0..j]= "ALTRUISTIC"时,需要枚举字符串S和T最后一个字符S[i]和T[j]对应的四种情况,即“字符-空白”“空白 字符”“字符 字符”“空白 空白”。
由于其中的“空白 空白”是多余的编辑操作,所以事实上只存在以下三种情况。
(1)源串S有字符X,目标串T空白,即“S:字符X,T:空白”。要让S变成T,则意味着源串S要删除字符X,可得方程dp[i−1][j]+1。
(2)源串S空白,目标串T有字符Y,即“S:空白,T:字符Y”。要让S变成T,则意味着源串S要插入字符Y,可得方程dp[i][ j−1]+1。
(3)源串S中的字符X与目标串T中的字符Y对应,即“S:字符X,T:字符Y”。要让S变成T,则意味着要把源串S中的字符X替换成目标串T中的字符Y,可得方程dp[i−1][j−1]+(s[i] ==t[j]?0:1)。
int minDistance(string word1,string word2)
{
int m = word1.length();
int n = word2.length();
vector<vector<int> >dp(m+1,vector<int>(n+1));
for(int i = 0;i<=m;++i)
{
for(int j = 0;j<=n;++j)
{
if(0==i)
dp[i][j] = j;
else if(0==j)
dp[i][j] = i;
else
{
dp[i][j] = min(dp[i-1][j-1]+(word1[i-1]==word2[j-1]?0:1),min(dp[i-1][j]+1,dp[i][j-1]+1));
}
}
}
return dp[m][n];
}