我们称一个字符串 S 包含字符串 T 是指 T 是 S 的一个子序列,即可以从字符串 S 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 T 完全一样。

给定两个字符串 S和 T,请问最少修改 S 中的多少个字符,能使 S 包含 T?

思路同编辑距离:

dp[ i ][ j ]: S通过删除和修改操作得到T的最少操作个数(删除不算操作个数)

考虑S[i]进行的操作:

(1)s[i]删除:如果删除s[i]ST匹配,那么必须保证s[1~i-1]和T[1~j]匹配

dp[i][j]=dp[i-1][j]

(2)s[i]修改:如果修改s[i]ST匹配,那么必须保证S[1~i-1]和T[1~j-1]匹配,但是如果s[i]==t[j],那么操作个数不需要加1

dp[i][j]=dp[i-1][j-1]+1或者0

初始化:

因为(i,j)只能由前一个退出,所以只需要初始dp[0][i]和dp[0][j]即可

dp[i][0]=0:无需修改

dp[0][i]=INF:不可能修改

注意:

(1)删除操作不算操作个数

(2)初始化问题

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
char s[1005],t[1005];
int dp[1005][1005];
string a,b;
const int INF=0X3f3f3f3f;

int main(){
    cin>>a;
    cin>>b;
    int n=a.size();
    int m=b.size();
    for(int i=0;i<n;i++){
        s[i+1]=a[i];
    }
    for(int i=0;i<m;i++){
        t[i+1]=b[i];
    }
    memset(dp,0x3f3f3f,sizeof(dp));
    for(int i=0;i<=n;i++){
        dp[i][0]=0;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
                dp[i][j]=min(dp[i][j],dp[i-1][j]);
                if(s[i]==t[j])dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
                else dp[i][j]=min(dp[i][j],dp[i-1][j-1]+1);
            }
        }
    cout<<dp[n][m];
    return 0;
    
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.