问最少操作多少次可以把字符串T变成S?
让串S和T的最长公共序列对齐,然后空出来的部分用'-'填充。
比如:S="ABCD",T="DBDE",对齐之后有
ABCD-
DB-DE
参照求LCS时的状态,可以设dp[i][j]表示将S[i]和T[j]对齐后,需要的最少操作。
则dp[i][j]=min(dp[i-1][j-1]+(S[i]!=T[j]),dp[i-1][j]+1,dp[i][j-1]+1)
#include<bits/stdc++.h> using namespace std; typedef __int64 LL; char S[1005],T[1005]; int dp[1001][1001]; int main() { int i,j; cin>>S>>T; int l1=strlen(S),l2=strlen(T); for(i=0;i<=l1;++i) dp[i][0]=i; for(i=0;i<=l2;++i) dp[0][i]=i; for(i=1;i<=l1;++i) for(j=1;j<=l2;++j) dp[i][j]=min(dp[i-1][j-1]+(S[i-1]!=T[j-1]),min(dp[i-1][j],dp[i][j-1])+1); printf("%d\n",dp[l1][l2]); return 0; }
空间复杂度优化:
#include<bits/stdc++.h> using namespace std; typedef __int64 LL; char S[1005],T[1005]; int dp[2][1001]; int main() { int i,j; cin>>S>>T; int l1=strlen(S),l2=strlen(T); for(i=0;i<=l2;++i) dp[0][i]=i; for(i=1;i<=l1;++i){ dp[i&1][0]=i; for(j=1;j<=l2;++j) dp[i&1][j]=min(dp[!(i&1)][j-1]+(S[i-1]!=T[j-1]),min(dp[!(i&1)][j],dp[i&1][j-1])+1); } printf("%d\n",dp[!(i&1)][l2]); return 0; }