Problem: 2050E - Three Strings
Language: C++20 (GCC 13-64)

Previous submission (verdict: Time limit exceeded on test 16):
#include<bits/stdc++.h>
using namespace std;

int f(string a,string b,string c,int i,int j,vector<vector<int>> &dp){
    if(i+j>=c.size()){
        return 0;
    }
    if(i>=a.size()){
        int g=0;
        for(int k=j;k<b.size();k++){
            if(b[k]!=c[k+i]){
                g++;
            }
        }
        return g;
    }
    if(j>=b.size()){
        int g=0;
        for(int k=i;k<a.size();k++){
            if(a[k]!=c[k+j]){
                g++;
            }
        }
        return g;
    }
    if(dp[i][j]!=-1){
        return dp[i][j];
    }
    int tk = 1e6;
        if(c[i+j]==a[i]){
            tk = f(a,b,c,i+1,j,dp);
        }
        else{
            tk = 1+f(a,b,c,i+1,j,dp);
        }
    int ntk = 1e6;
        if(c[i+j]==b[j]){
            ntk = f(a,b,c,i,j+1,dp);
        }
        else{
            ntk = 1+f(a,b,c,i,j+1,dp);
        }
    return dp[i][j]=min(tk,ntk);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        string a,b,c;
        cin>>a>>b>>c;
        int n = a.size();
        int m = b.size();
        vector<vector<int>> dp(n+1,vector<int>(m+1,-1));
        int g = f(a,b,c,0,0,dp);
        cout<<g<<endl;
    }
}

Submission (verdict: Accepted):
#include<bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    int t;
    cin >> t;

    while (t--) {
        string a, b, c;
        cin >> a >> b >> c;

        int n = a.size();
        int m = b.size();

        // DP table: dp[i][j] represents the minimum changes for a[0..i] and b[0..j] to form c[0..i+j-1]
        vector<vector<int>> dp(n + 1, vector<int>(m + 1, 1e9));

        // Base cases
        dp[n][m] = 0; // Both a and b are exhausted

        // Filling the table bottom-up
        for (int i = n; i >= 0; --i) {
            for (int j = m; j >= 0; --j) {
                // If we exhausted `a`, handle the remaining `b` part
                if (i == n) {
                    int g = 0;
                    for (int k = j; k < m; ++k) {
                        g += (b[k] != c[k + i]);
                    }
                    dp[i][j] = g;
                    continue;
                }
                // If we exhausted `b`, handle the remaining `a` part
                if (j == m) {
                    int g = 0;
                    for (int k = i; k < n; ++k) {
                        g += (a[k] != c[k + j]);
                    }
                    dp[i][j] = g;
                    continue;
                }

                // Transition:
                // Take from `a`
                if (c[i + j] == a[i]) {
                    dp[i][j] = min(dp[i][j], dp[i + 1][j]);
                } else {
                    dp[i][j] = min(dp[i][j], 1 + dp[i + 1][j]);
                }

                // Take from `b`
                if (c[i + j] == b[j]) {
                    dp[i][j] = min(dp[i][j], dp[i][j + 1]);
                } else {
                    dp[i][j] = min(dp[i][j], 1 + dp[i][j + 1]);
                }
            }
        }

        // Result: minimum changes starting from dp[0][0]
        cout << dp[0][0] << "\n";
    }

    return 0;
}