2553. 最优包含

题目链接

2553. 最优包含

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

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

输入格式

输入两行,每行一个字符串。

第一行的字符串为 \(S\),第二行的字符串为 \(T\)

两个字符串均非空而且只包含大写英文字母。

输出格式

输出一个整数,表示答案。

数据范围

\(1≤|T|≤|S|≤1000\)

输入样例:

ABCDEABCD
XAABZ

输出样例:

3

解题思路

dp

  • 状态表示:\(f[i][j]\) 表示 \(s\) 的前 \(i\) 的字符修改后包含 \(t\) 的前 \(j\) 个字符的最少修改次数

  • 状态计算:

    • \(s[i]=t[j]\)\(f[i][j]=f[i-1][j-1]\)
    • \(s[i]\neq t[j]\)\(f[i][j]=min(f[i-1][j],f[i-1][j-1]+1)\)
      分析:最后两个字符相等,则只需要管前面的字符即可,否则考虑 \(s\) 的第 \(i\) 个字符是否需要修改

最后初始化时,\(t\) 为空串时,\(f[i][0]=0\),因为空串是任意一个串的子串

  • 时间复杂度:\(O(nm)\)

代码

// Problem: 最优包含
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/2555/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1005;
int n,m,f[N][N];
string s,t;
int main()
{
    cin>>s>>t;
    n=s.size(),m=t.size();
	s=' '+s,t=' '+t;
	memset(f,0x3f,sizeof f);
	for(int i=0;i<=n;i++)f[i][0]=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(i<j)continue;
			if(s[i]==t[j])f[i][j]=f[i-1][j-1];
			else
				f[i][j]=min(f[i-1][j],f[i-1][j-1]+1);
		}
	cout<<f[n][m];
    return 0;
}
posted @ 2022-04-06 16:13  zyy2001  阅读(55)  评论(0编辑  收藏  举报