タイトルリンク:https://atcoder.jp/contests/abc185/tasks/abc185_e
本旨:
2つの文字列が与えられた場合、2つの文字列内の任意の文字を削除できます
最終的な目標は、2つの弦を同じ長さにすることです
重みを定義しますx =削除された文字の総数、y =最終文字列の下の位置A [i]!= B [i]の総数
x + yの最小値を尋ねる
質問のアイデア:
クラシックストリングdp
dp [i] [k]が文字列Aの最初のiと文字列の最初のBを表し、同じ長さの文字列を形成することを考えると、x + yの最小値
次に、任意の位置(i、k)
あれは:
1. iを削除し、kを保持します
2. kを削除し、iを保持します
3.iを削除してkを削除します
4. iを維持し、kを維持します
4つのケースを列挙して転送するだけで、3番目のケースは無意味なので列挙する必要はありません。
したがって、境界条件を考慮してください
これはABCakです
コード:
/*** keep hungry and calm CoolGuang! ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18;
const ll maxn = 4e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll dp[1005][1005];
ll a[maxn],b[maxn];
int main(){
read(n);read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=m;i++) read(b[i]);
for(int i=1;i<=n;i++)
for(int k=1;k<=m;k++)
dp[i][k] = INF;
dp[0][0] = 0;
for(int i=1;i<=n;i++) dp[i][0] = i;
for(int k=1;k<=m;k++) dp[0][k] = k;
for(int i=1;i<=n;i++){
for(int k=1;k<=m;k++){
dp[i][k] = min(dp[i-1][k]+1,dp[i][k-1]+1);
dp[i][k] = min(dp[i][k],dp[i-1][k-1]+(a[i]!=b[k]));
}
}
ll ans = INF;
printf("%lld\n",dp[n][m]);
return 0;
}
/***
2 4
2 3
1 1 2 3
***/