例题:
http://www.51nod.com/Challenge/Problem.html#problemId=1183
输入
第1行:字符串a(a的长度 <= 1000)。 第2行:字符串b(b的长度 <= 1000)。
输出
输出a和b的编辑距离
输入样例
kitten
sitting
输出样例
3
分析:
设字符串S和T的长度分别为m和n, 两者的编辑距离表示为dp[m][n]. 则对序列进行操作时存在以下几种情况:
a, 当S和T的末尾字符相等时, 不需要增加计数. 则满足条件: dp[m][n] = dp[m - 1][n - 1].
b, 当S和T的末尾字符不相等时, 则需要对两者之一的末尾进行编辑, 相应的计数会增加1:.
, 对S或T的末尾进行修改, 以使之与T或S相等, 则此时dp[m][n] = dp[m - 1][n - 1] + 1;
删除S末尾的元素, 使S与T相等, 则此时dp[m][n] = dp[m - 1][n] + 1;
删除T末尾的元素, 使T与S相等, 则此时dp[m][n] = dp[m][n - 1] + 1;
, 在S的末尾添加T的尾元素, 使S和T相等, 则此时S的长度变为m+1, 但是此时S和T的末尾元素已经相等, 只需要比较S的前m个元素与T的前n-1个元素, 所以满足dp[m][n] = dp[m][n - 1] + 1;
在T的末尾添加S的尾元素, 使T和S相等, 此时的情况跟b4相同, 满足dp[m][n] = dp[m - 1][n] + 1;
比较特殊的情况是, 当S为空时, dp[0][n] = n; 而当T为空时, dp[m][0] = m; 这个很好理解, 例如对于序列""和"abc", 则两者的最少操作为3, 即序列""进行3次插入操作, 或者序列"abc"进行3次删除操作.
还有一点就是dp[0][0]=0;
综上所述 递推公式就是: dp[i][j]=dp[i-1][j-1](S的第i项和t的第j项相等时)
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1)
AC代码:
#include<iostream> #include<algorithm> #include<string> #include<cstring> using namespace std; char a[1000+10]; char b[1000+10]; int dp[1000+10][1000+10]; int main(){ scanf("%s %s",a+1,b+1); a[0]=b[0]='0'; int n=strlen(a); int m=strlen(b); for(int i=1;i<=n;i++) dp[0][i]=i; for(int i=1;i<=m;i++) dp[i][0]=i; dp[0][0]=0;
//以上为初始化,,以下为核心部分 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]; else { int temp=min(dp[i][j-1]+1 ,dp[i-1][j]+1 ); dp[i][j]=min(temp,dp[i-1][j-1]+1 ); } } cout<<dp[n][m]<<endl; return 0; }