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\) 个字符是否需要修改
- \(s[i]\neq t[j]\),\(f[i][j]=min(f[i-1][j],f[i-1][j-1]+1)\)
最后初始化时,\(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;
}