题意:给你两个字符串,让你把第一个字符串转化为第二个字符串,问你最少需要多少次操作(添加,删除,更改),属于lcs的变形题:
定义dp[i][j]为第一个串的前i个字符转化为第二个串的前j个字符所需最小的步骤,这是满足最优子结构性质的,因为如果转移到dp[i][j]的那个状态不是可以转化过来的状态中最优的,我们可以用最优的替代它
那么怎么转移呢?显然如果s1[i]=s2[j](s1为第一个串,s2为第二个串),那么dp[i][j]=dp[i-1][j-1],如果不等,怎么办?根据题目给定的三种操作,我们可以从三个之前不同的状态转移过来
如果使用替换操作,那么到dp[i][j]的最小代价应该为dp[i-1][j-1]+1,因为s1[i]!=s2[j],只要把s1[i]换成s2[j]或者把s2[j]换成s1[i]即可
如果使用删除操作,那么到dp[i][j]的最小代价应该为dp[i][j-1]+1,因为此时在s2中加入一个空格,就相当于在s1中删除一个字符
如果使用插入操作,那么到dp[i][j]的最小代价应该为dp[i-1][j]+1,此时在s1中插入一个字符
所以,在三种情况中取一个最小值就行
AC代码:#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 1005
using namespace std;
int dp[N][N];
char s1[N],s2[N];
int main()
{
int n,m;
while(~scanf("%d%s%d%s",&n,s1,&m,s2)){
for(int i=0;i<=n;++i) dp[i][0]=i;
for(int i=0;i<=m;++i) dp[0][i]=i;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
if(s1[i-1]==s2[j-1]) dp[i][j]=dp[i-1][j-1];
else dp[i][j]=min(min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
}
cout<<dp[n][m]<<endl;
}return 0;
}