传送门:一本通评测1276
【题目描述】
设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
1、删除一个字符;
2、插入一个字符;
3、将一个字符改为另一个字符。
对任意的两个字符串A和B,计算出将字符串A变换为字符串B所用的最少字符操作次数。
【输入】
第一行为字符串A;第二行为字符串B;字符串A和B的长度均小于2000。
【输出】
只有一个正整数,为最少字符操作次数。
【输入样例】
sfdqxbw
gfdgw
【输出样例】
4
【思路】
动态规划思想,题目问的是字符串a到字符串b的编辑距离。动态规划有最优子问题结构,子问题的形式和原问题结构相似,且规模减小。那么在考虑问题的时候,往前想一步:
·如果字符串a前alen-1个字符已经和b相同,那么当前a到b的编辑距离就是1(删除最后一个)
·如果字符串a和b的前blen-1个字符相同,那么当前a到b的距离也是1(添加一个)
·如果a的前alen-1个字符和b的blen-1个字符已经相同,如果a的最后一个字符和b的最后一个字符相同,那么a到b的编辑距离为0,否则为1(改变一次)
设状态为dp[i][j],表示字符串a的前i个字符到字符串b的前j个字符的编辑距离,由以上分析,可以写出该dp的状态转移方程:
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1])(a的第i个字符和b的第j个字符相同)
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1)(a的第i个字符和b的第j个字符不同)
详细代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 2000+5 4 int d[maxn][maxn]; 5 int min(int a,int b,int c) 6 { 7 if(a>b) swap(a,b); 8 if(a>c) swap(a,c); 9 return a; 10 } 11 int main() 12 { 13 char a[maxn],b[maxn]; 14 cin>>a; 15 cin>>b; 16 memset(d,0,sizeof(d)); 17 int len1=strlen(a); 18 for(int i=1;i<=len1;i++) 19 { 20 d[i][0]=i; 21 } 22 int len2=strlen(b); 23 for(int i=1;i<=len2;i++) 24 { 25 d[0][i]=i; 26 } 27 for(int i=1;i<=len1;i++) 28 { 29 for(int j=1;j<=len2;j++) 30 { 31 d[i][j]=min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+(a[i-1]==b[j-1]?0:1)); 32 } 33 } 34 cout<<d[len1][len2]<<endl; 35 return 0; 36 }