给定两个字符串S和T,对于T我们可以进行三种操作
(1)在任意位置增加字符
(2)删除字符
(3)替换字符
问最少多少次能把T变成S?
设f(i,j)是S的前i位和T的前j位对齐的最小花费
接下来分析每一位
(1)如果S[i]==T[j],就不用任何修改,那么最小花费是f(i-1,j-1)
(2)如果S[i]!=T[j],那么最小花费是f(i-1,j-1)+1
(3)如果S的前i位已经和T的前(j-1)位对齐了,那么最小花费是f(i,j-1)+1
(4)如果S的前(i-1)位已经和T的前j位对齐了,那么最小花费是f(i-1,j)+1
综上,递推式是f(i,j)=min(f(i,j)+cost,f(i-1,j)+1,f(i,j-1)+1)
最后分析一下初值:
f(i,0)=i
f(0,j)=j
这就相当与把S或T的前i或j位全部删除的样子(好残忍……)

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int f[1005][1005]; int main() { char a[1005],b[1005]; int lena,lenb,i,j,cost,mincost; while(~scanf("%s%s",a,b)) { lena=strlen(a); lenb=strlen(b); for(i=0; i<lena; i++) f[i][0]=i; for(i=0; i<lenb; i++) f[0][i]=i; for(i=1; i<=lena; i++) for(j=1; j<=lenb; j++) { if(a[i-1]==b[j-1]) cost=0; else cost=1; mincost=min(f[i][j-1]+1,f[i-1][j]+1); f[i][j]=min(mincost,f[i-1][j-1]+cost); } printf("%d ",f[lena][lenb]); memset(f,0,sizeof(f)); } return 0; }